Introduction

This tutorial will follow most steps from the Moving Pictures Tutorial which might be found on the qiime2 website (https://docs.qiime2.org/2018.6/tutorials/moving-pictures/) and integrate it with separate instructions for the ITS sequences. These scripts are based on the current release of qiime2 (2018.06), but keep in mind that the authors tend to change the tutorial page and update their commands at every new release of qiime2.

You can ask the Hipergator staff to update qiime2 on the support page, but they seem to keep it pretty current; be sure to modify the “module load” command accordingly in all scripts if you want to use different version. Most of the scripts are based on the previous 16Sr-RNA Preprocessing Pipeline.

Preliminary steps:

To login on Hipergator follow the procedures reported at https://help.rc.ufl.edu/doc/Getting_Started#Connecting_to_HiPerGator. In the same page, there are also instructions for how to upload data to Hipergator. However, BEFORE uploading the data, create a folder structure that will be useful for your purposes. In this case, I will be showing both 16S and ITS pipelines, and then how to merge the tables.

After logging in, navigate to your working directory and create the necessary subfolders:

cd /ufrc/strauss/your_account/your_working_directory 
mkdir 16S

mkdir ITS

mkdir merged

If you want to know who’s currently working on hipergator, or if you want to check how your job is performing, you can enter this command:

watch squeue -A strauss -O jobid:10,username,name,partition,state:10,reason:10,cores,gres:10,tres:30,timeused:10

Try keep the sums of the allocated resources lower than the account limits: some batches may just wait for the excess resources until free, others will just break the currently running batches. To exit the activity monitor press ctrl + c.

16S pipeline

0_setup.sh

First things first: once you have your designed working folder, move your raw sequences into a raw_seqs directory created therein. Secondly, it is useful to have a single folder named scripts from where to edit and launch your bash commands. All scripts will also need the logs directory which you should create manually, in order for your commands will produce their logfile for backtrace.

NOTE: contrarily to qiime1, qiime2 doesn’t need (well, it won’t actually accept) uncompressed fastq files. Don’t `gunzip` them. 
NOTE2: these scripts work only for already demultiplexed paired sequences. If you have multiplexed sequences or single reads you should head to the qiime2 website and adjust the parameters of all scripts accordingly.

*IMPORTANT*: before going on with the scripts make sure there are no duplicates in the sample file names (i.e. the part of the file name that is before `_R1_` or `_R2_`)!! Change file names accurately and then proceed with the next script.
cd 16S
mkdir raw_seqs
mkdir logs
mkdir scripts

Now move your compressed sequence files in the raw_seqs directory following the instructions frtom the Hipergator wiki page. Then start writing the first bash script, using

nano scripts/0_setup.sh

You will be prompted with a text editor where you should copy-paste the following:

#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J setup
#SBATCH -N 1
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/0_setup_%j.out                                      #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Setup data directory and copy raw_seqs contents
#
################################################################################

# ----------------Housekeeping--------------------
rm -rf data
mkdir data
mkdir data/raw_data

# ------------------Commands----------------------

# If sequences are individual directories (if not, comment this out):
for dir in raw_seqs/*; do
    cp $dir/* data/raw_data/.
done 

# Fix names: this depends of course on how your files are named. CHECK THEM!
for file in data/raw_data/*.gz; do
    mv $file ${file/Strauss?-/};
    mv $file ${file/Strauss??-/};
    mv $file ${file/Strauss???-/};
done

date

Exit using ctrl + X and save with Y. Then do

nano scripts/0_setup.sh

1_import.sh

Estimated time: few minutes

Now it is time to import our sequences. This script will create a Qiime2 artifact which contains the sequences data (they call it FeatureData[Sequence]). This script differs from the Moving Pictures Tutorial, because it is tailored for paired end demultiplexed sequences.

Qiime2 .qza artifacts are actually compressed files which contain a typical qiime1 output file (which might be a biom table, a taxonomy table or a fasta file) hidden in some subfolders and accompanied by the files necessary for generating the visualization. Visualization are the “big thing” of qiime2, which allows the implementation of a graphic interface as well, and allow to view the data graphically with interactive plots and tables.

The script produces a visualization which summarizes the quality data and the lengths of your reads (i.e. similar to the stats.txt produced by the USEARCH pipeline commands). This can be viewed by loading it on the https://view.qiime2.org website.

NOTE: HiperGator does not have a visual interface, at least in strauss partition. Therefore, it is likely that when the scripts will look for matplotlib to build the visualization file, they would return an error. 

To avoid that, simply write an empty file in your config with

nano ~/.config/matplotlib/matplotlibrc

You will then be prompted an empty page in which you will write this line only

backend : agg

Exit using ctrl + X and save with Y. Then do

nano scripts/1_import.sh

And copypaste the following

#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J q2_import
#SBATCH --time=2:00:00                                            #Maximum number of hours
#SBATCH -N 1                                                      #Number of nodes
#SBATCH --mem=10g                                                 #Allocated RAM
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/1_q2_import_%j.out                                #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Import fastq.gz files into a .qza file
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping---------------------
rm -r demux*.q*
cd data

# ----------------Commands------------------------

#Import Data in qiime2 artifact
qiime tools import \
  --type 'SampleData[PairedEndSequencesWithQuality]' \
  --input-path raw_data \
  --input-format CasavaOneEightSingleLanePerSampleDirFmt \
  --output-path demux-paired-end.qza

# Create Data Visuailizations
# ATTENTION: if your demux give you "invalid DISPLAY variable error" it's because you don't have graphic interface.
# To solve it create a file using nano ~/.config/matplotlib/matplotlibrc
# And write the following
# backend : agg

qiime demux summarize \
  --i-data demux-paired-end.qza \
  --o-visualization demux-paired-end.qzv

# Unload modules:
module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/1_import.sh

After the script finishes, load the demux-paired-end.qzv file in the https://view.qiime2.org website. You will see when the quality of your reads degenerates through an interactive box-plot. Through this box-plot, you can determine at which length you would truncate the forward and the reverse reads respectively. You will need these values for the next script. The idea is, of course, to find a compromise between retaining the higher number of reads and retaining the best quality of them.

2_dada2.sh

Estimated time: many hours The next step is dereplication. This script uses the DADA2 R package (https://www.nature.com/articles/nmeth.3869) which is implemented in qiime2 pipeline.

Note: For a comparison of DADA2 amplicon sequence variants calling against the current OTU picking algorithm (2016) check https://benjjneb.github.io/dada2/SotA.html. 

Accuracy: DADA2’s crucial advantage is that it uses more of the data. The DADA2 error model incorporates quality information, which is ignored by all other methods after filtering. The DADA2 error model incorporates quantitative abundances, whereas most other methods use abundance ranks if they use abundance at all. The DADA2 error model identifies the differences between sequences, eg. A->C, whereas other methods merely count the mismatches. DADA2 can parameterize its error model from the data itself, rather than relying on previous datasets that may or may not reflect the PCR and sequencing protocols used in your study.

Performance: DADA2’s computational scaling gains come from the fact that it infers sequences exactly rather than constructing OTUs. De novo OTUs cannot be compared across samples unless all samples were pooled during OTU construction. However, exact sequences are comparable across samples, as exact sequences are consistent labels. Thus DADA2 can analyze each sample independently, resulting in linear scaling with sample number and trivial parallelization.

It is extremely accurate and lowers the fraction of false positives. In our previous comparisons against the USEARCH clustering method, DADA2 was shown to better discern the samples and result in a much higher diversity. Technically, it relies on inference over sequences rather than OTU clustering, and this is why it is able to better discern a genetic variation from a different species (see website for more info).

The script will create a new folder called features and perform its analysis there which include: denoising of the sequences, dereplication, chimera removal all in one step. The script uses a parallelized version of the DADA2 algorithm, splitting the works on 12 cores. The more the cores, the shorter the time it will take. It will result in a table.qza file, which contains an atypical biom table, quasi-HDF5, and a rep-seqs.qza file, from which you can extract a the fasta file containing representative sequences. Both of them will be used in the following scripts.

NOTE: in order to truncate low quality regions at the end of the sequences, the script needs you to specifiy the length of each sequence (fw and rev) in number of bases. Use the quality plots from the .qzv file produced in the previous step to determine such number and insert it in place of the two placeholders specified.
nano scripts/2_dada2.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J par_dada2
#SBATCH -N 1
#SBATCH --time=24:00:00
#SBATCH --mem=40g                                                         #TOTAL RAM PER TASK
#SBATCH -n 12                                                               #NUMBER OF CPUS PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/2_q2_dada2_%j.out                                   #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Filters paired-end sequences based on quality, merges dereplicates them 
# using DADA2 algorithm. Includes chimera removal.
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
rm -r features
mkdir features
cp data/demux-paired-end.qza features/dada2input.qza
cd features


# ----------------Commands------------------------

qiime dada2 denoise-paired \
  --i-demultiplexed-seqs dada2input.qza \
  --p-n-threads 0 \
  --p-trunc-len-f \    #INSERT NUMBER OF BASES BEFORE THE FORWARD SLASH AND DELETE THIS INSTRUCTION
  --p-trunc-len-r \   #INSERT NUMBER OF BASES BEFORE THE FORWARD SLASH AND DELETE THIS INSTRUCTION
  --o-table table.qza \
  --o-denoising-stats stats.qza \
  --o-representative-sequences rep-seqs.qza 

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/2_dada2.sh

3_feature_table.sh

Estimated time: minutes

This script will build a feature table, which is a similar concept of the OTU table from qiime1. Before applying this script it is highly recommended to check the mapping file, since errors in file names will be carried on until the end of the analysis. A good tool to validate qiime1 and qiime2 mapping files is the Keemei add-on for google spreadsheet, which runs in chrome (can be added from the chrome store http://keemei.qiime.org). Once installed, you need to open an empty google spreadsheet, then go to add-on, Keemei, and validate the mapping file for the version of qiime required. The process is interactive and will guide you through duplicate values, formatting issues, etc.

Finally, the script will also produce visualization of both the sequence file (rep-seqs.qza) and of the feature table (table.qza), which will be useful for the next steps.

nano scripts/3_feature_table.sh 
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss      
#SBATCH -J q2_feattab
#SBATCH -N 1
#SBATCH --time=2:00:00          
#SBATCH --mem=10g                                                       #TOTAL RAM PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/3_q2_feature_table_%j.out                           #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Build feature table required for further analysis
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# Housekeeping:
cd features
rm table.qzv
rm rep-seqs.qzv
rm reindexed-table.qza

# ----------------Commands------------------------

qiime feature-table summarize \
  --i-table table.qza \
  --o-visualization table.qzv \
  --m-sample-metadata-file  ../blabla           #INSERT PATH TO VALIDATED MAPPING FILE

qiime feature-table tabulate-seqs \
  --i-data rep-seqs.qza \
  --o-visualization rep-seqs.qzv

# Unload modules:
module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/3_feature_table.sh   

4_taxonomy.sh

Estimated time: hours

This script provides the taxonomic assignments to your sequences. To do so, it will use a pre-trained dataset, which is a sequence database inferred through the application of the naïve Bayes classifier, and use a machine learning algorithm to assign the taxonomy of your sequence to that classifier. Therefore, it requires high computational power, and for this reason the script allocates many processors into which the script is parallelized, and a high amount of memory as well. The qiime2 website provides a classifier for Greengenes 13_8 and a classifier for SILVA 119; be careful to download the full sequences and not the truncated sequences for the V3 region only.

nano scripts/4_taxonomy_SILVA.sh        
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J q2_scikit_tax
#SBATCH -N 1
#SBATCH --time=72:00:00
#SBATCH --mem=30g                                                         #TOTAL RAM PER TASK       
#SBATCH -n 8                                                                #NUMBER OF CPUS PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/4_q2_tax_SILVA128_%j.out                            #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Assign taxonomy using a pre-trained scikit classifier version 0.19.1
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
cd features
rm taxonomy.qza
rm taxa-bar-plots.tsv
rm taxonomy.qzv

# ----------------Commands------------------------
qiime feature-classifier classify-sklearn \
  --i-reads rep-seqs.qza \
  --o-classification taxonomy.qza \
  --i-classifier  /ufrc/strauss/blabla          #INSERT PATH TO YOUR PRETRAINED DATABASE 

qiime metadata tabulate \
  --m-input-file taxonomy.qza \
  --o-visualization taxonomy.qzv

qiime taxa barplot \
  --i-table table.qza \
  --i-taxonomy taxonomy.qza \
  --o-visualization taxa-bar-plots.qzv \
  --m-metadata-file ../blabla                     #INSERT PATH TO VALIDATED MAPPING FILE


# Unload modules:
module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/4_taxonomy_SILVA.sh      

Optionally, you can train your own classifier. For that, you will first need to download a fasta database and the related taxonomy file (i.e. SILVA 128). Once you downloaded it you have to know: - your fw primer sequence - your rev primer sequence - the maximum length to your reads (single, not merged) Together with the fasta and taxonomy files, these are the inputs of the opt1_train_scikit.sh script, which will build another trained classifier from your database, truncated at the region of interest (which will reduce the computational power and time required for the taxonomy script).

NOTE: there is a SILVA pre-trained database for version 132 available on the qiime2 website. I think it could be used for our primers, but need to double-check.
nano scripts/opt_train_sklearn.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J scikit_training
#SBATCH -N 1
#SBATCH --time=24:00:00
#SBATCH --mem=40g                                     #TOTAL RAM PER TASK
#SBATCH -D /ufrc/strauss/                         #PATH TO A DATABASE FOLDER OF YOUR CHOICE
#SBATCH -o logs/q2_scikit_train_%j.out          #PATH OF LOG FILE

date;hostname;pwd

# ----------------Housekeeping--------------------
rm -r   #NAME OF THE NEW DATABASE FOLDER 
mkdir   #NAME OF THE NEW DATABASE FOLDER
cd  #NAME OF THE NEW DATABASE FOLDER

# ----------------Load Modules--------------------
module load qiime2

# ---------------Commands-------------------------

qiime tools import \
  --type 'FeatureData[Sequence]' \
  --output-path imported-fasta-database.qza \
  --input-path /ufrc/strauss/blabla   #INSERT PATH TO THE rep_set/rep_set_all/97/97_otus.fasta FILE


qiime tools import \
  --type 'FeatureData[Taxonomy]' \
  --source-format HeaderlessTSVTaxonomyFormat \
  --output-path imported-taxonomy.qza \
  --input-path /ufrc/strauss/blabla #INSERT PATH TO THE taxonomy_all/97/consensus_taxonomy_7_levels.txt FILE

qiime feature-classifier extract-reads \
  --i-sequences imported-fasta-database.qza  \
  --p-f-primer  \       #INSERT FW PRIMER SEQUENCE BEFORE THE FW SLASH AND DELETE THIS INSTRUCTION
  --p-r-primer  \       #INSERT REV PRIMER SEQUENCE BEFORE THE FW SLASH AND DELETE THIS INSTRUCTION
  --p-trunc-len  \      #INSERT LENGTH OF TRIMMED SEQUENCES BEFORE THE FW SLASH AND DELETE THIS 
  --o-reads truncated-imported-db.qza

qiime feature-classifier fit-classifier-naive-bayes \
  --i-reference-reads truncated-imported-db.qza \
  --i-reference-taxonomy imported-taxonomy.qza \
  --o-classifier    /ufrc/strauss/blabla                      #INSERT NAME OF YOUR FINAL CLASSIFIER

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/opt_train_sklearn.sh

5_PICRUST.sh

To do the metabolic prediction in PICRUST just use the following script. It will reassign the taxonomy to the Greengeenes database (which…) in qiime1 so be sure to have a the necessary files as well.

NOTE: At the time of writing, PICRUST2 is still in beta (https://github.com/picrust/picrust2) but might be worth keeping an eye on.

The results are stored as predicted_metagenomes.L3.biom and metagenome_predictions.biom. I make some plots using its own commands, but you’d better do them anywhere else.

nano scripts/5_PICRUST.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -A strauss
#SBATCH -J PiCRUSt
#SBATCH -N 1
#SBATCH --time=72:00:00
#SBATCH --mem=25g                                                         #TOTAL RAM PER TASK       
#SBATCH -n 8                                                                #NUMBER OF CPUS PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/16S  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/5_PICRUSt_%j.out                                    #PATH OF LOG FILE

date;hostname;pwd

################################################################################
#
# Predict functionalities of the genome from taxonomical assignments using KeggO
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
rm -r PICRUSt
mkdir PICRUSt

# ----------------Commands------------------------
cp features/table.qza PICRUSt/imptab.qza

qiime tools export \
 --input-path features/rep-seqs.qza \
  --output-path PICRUSt

# Switch modules:
module unload qiime2
module load qiime/1.9.1

cd PICRUSt
echo "pick_otus:enable_rev_strand_match True"  >> $PWD/otu_picking_params_97.txt
echo "pick_otus:similarity 0.97" >> $PWD/otu_picking_params_97.txt

pick_closed_reference_otus.py \
 -i dna-sequences.fasta \
 -o gg \
 -a -O 8 \
 -p otu_picking_params_97.txt \
 -r /ufrc/strauss/blabla \        #INSERT PATH TO THE gg_13_8_otus/rep_set/97_otus.fasta FILE AND DELETE THIS INSTRUCTION
 -t /ufrc/strauss/blabla          #INSERT PATH TO THE gg_13_8_otus/taxonomy/97_otu_taxonomy.txt FILE

filter_taxa_from_otu_table.py \
  -i gg/*.biom \
  -o table_wo_chl_mit.biom \
  -n c__Chloroplast,f__Mitochondria

mv table_wo_chl_mit.biom picrust_input.biom

filter_otus_from_otu_table.py \
 -i picrust_input.biom \
 -o closed_otu_table.biom \
 --negate_ids_to_exclude \
 -e /ufrc/strauss/blabla        #INSERT PATH TO THE gg_13_8_otus/rep_set/97_otus.fasta FILE

filter_samples_from_otu_table.py \
 -i picrust_input.biom \
 -o closed_otu_table_filt.biom \
 -n 1
module purge
module load gcc/5.2.0
module load picrust/1.1.3

normalize_by_copy_number.py \
 -i closed_otu_table_filt.biom \
 -o normalized_otus.biom

predict_metagenomes.py -i normalized_otus.biom -o metagenome_predictions.biom -a nsti_per_sample.tab

categorize_by_function.py -i metagenome_predictions.biom -c KEGG_Pathways -l 3 -o predicted_metagenomes.L3.biom

metagenome_contributions.py -i normalized_otus.biom -o ko_metagenome_contributions.tab --load_precalc_file_in_biom --suppress_subset_loading

categorize_by_function.py -i metagenome_predictions.biom -c "KEGG_Pathways" -l 2 -o metagenome_at_level2.biom

module purge
module load qiime/1.9.1

biom convert \
 -i predicted_metagenomes.L3.biom \
 -o predicted_metagenomes.L3.tsv \
 --to-tsv \
 --table-type "OTU table"

sort_otu_table.py -i metagenome_predictions.biom  -o metagenome_predictions.by_category.biom -s YOUR_CATEGORY -m ../../mapping.txt #INSERT YOUR OWN CATEGORY AND PATH TO VALIDATED MAPPING FILE

echo "summarize_taxa:md_identifier    KEGG_Pathways" >> $PWD/qiime_params.txt
echo "summarize_taxa:absolute_abundance   True" >> $PWD/qiime_params.txt
echo "summarize_taxa:level    2" >> $PWD/qiime_params.txt

summarize_taxa_through_plots.py -i metagenome_at_level2.biom -p qiime_params.txt -o plots_at_level2

module unload qiime

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/5_PICRUST.sh

ITS pipeline

The ITS pipeline is very similar to the 16S pipeline, BUT it has the following major differences: - ITS1 sequences contain parts of the 8S unit and of the ITS2 sequences which must be trimmed. - ITS sequences are not all the same length, contrary to 16S. Therefore, DADA2 require different parameters. - UNITE database is used for ITS sequences instead of SILVA database.

NOTE: the most recent version of qiime2 include an ITS pipeline tutorial, which I haven't looked at the moment of writing.

0_setup.sh

cd ITS
mkdir raw_seqs
mkdir logs
mkdir scripts

Now move your compressed sequence files in the raw_seqs directory following the instructions frtom the Hipergator wiki page. Then start writing the first bash script, using

nano scripts/0_setup.sh
#!/bin/bash

#SBATCH --account=strauss
#SBATCH --job-name=setup
#SBATCH --ntasks=1
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/0_setup_%j.out
date;hostname;pwd

################################################################################
#
# Setup data directory and copy raw_seqs contents
#
################################################################################

##### Setup #####
# Load module(s):

# Housekeeping:
rm -rf data

# Make necessary directories:
mkdir data
mkdir data/raw_data

##### Run commands #####
# If sequences are individual directories (if not, comment this out):
for dir in raw_seqs/*; do
    cp $dir/* data/raw_data/.
done 

cd data/raw_data
gunzip *.gz

# Fix names: this depends of course on how your files are named. CHECK THEM!
for file in data/raw_data/*.gz; do
    mv $file ${file/Sarah?-/};
    mv $file ${file/Sarah??-/};
    mv $file ${file/Sarah???-/};
done

# Move files into their respective directory:
mkdir R1s
mkdir R2s
mv *_R1_* R1s/.
mv *_R2_* R2s/.

# Concatenate into a single file
cat R1s/* >> R1.fq
cat R2s/* >> R2.fq

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/0_setup.sh

1_merge_and_trim.sh

This is the first difference: instead of using directly DADA2 to merge the pired ends, we will use PEAR (https://sco.h-its.org/exelixis/web/software/pear/) which will retain the quality of the base calls. Then we will trim the sequences removing the unwanted regions using cutadapt (http://journal.embnet.org/index.php/embnetjournal/article/view/200, now available also in Qiime2, but here used as is).

IMPORTANT: The script will extract the barcodes from the sequences using qiime1. It will then produce a txt file which contains the barcodes associated to every file. You need to write those barcodes in your mapping file, in the column BarcodeSequence otherwise you will not be able to import the sequence. Pay attention to the correct associations between barcodes and file names when building your mapping files!!!

nano scripts/1_merge_and_trim.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --account=strauss
#SBATCH --job-name=merge_trim
#SBATCH --time=8:00:00
#SBATCH --ntasks=1
#SBATCH -n 8
#SBATCH --mem=20g
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/1_pear_cutadapt_%j.out
date;hostname;pwd

################################################################################
#
# Merge ITS paired ends and trims away regions outside primers
# 
################################################################################

# ----------------Load Modules--------------------
module load pear

# ----------------Housekeeping---------------------
rm -r features
mkdir features
cd data
rm -r merge.pear.*
rm no*.fastq
rm trimmed-seqs.fastq


# ----------------Commands------------------------

# Merge paired end reads
pear -j 8 -y 15G\
  -f raw_data/R1.fq \
  -r raw_data/R2.fq \
  -o merge.pear

module unload pear
module load cutadapt

#Trim out primers 
cutadapt -a GCATCGATGAAGAACGCAGC -o nofw.fastq merge.pear.assembled.fastq 
cutadapt -g CTTGGTCATTTAGAGGAAGTAA -o noprimer-seqs.fastq nofw.fastq

#Trim out 5.8S and SSU
cutadapt -g CTTGGTCATTTAGAGGAAGTAAAAGTCGTAACAAGGTTTCCGTAGGTGAACCTGCGGAAGGATCATT -a AACTTTCAACAACGGATCTCTTGGYTCTSGCATCGATGAAGAACGCAGC -o trimmed-seqs.fastq noprimer-seqs.fastq

module unload cutadapt 

mv trimmed-seqs.fastq ../features/trimmed-seqs.fastq
cd ../features

#Extract barcodes, necessary to import into Qiime2
module load qiime

extract_barcodes.py \
 -f trimmed-seqs.fastq \
 -c barcode_in_label \
 --char_delineator ':' \
 --bc1_len  10 \
 -o .

module unload qiime

gzip *
mv trimmed-seqs.fastq.gz sequences.fastq.gz

#In case you need to rebuild your mapping file, you can extract filenames and first
#lines from your original sequences with 
cd ../data/raw_data/R1s
head -n1 *.fastq > ../sequences_with_headers.txt

#You will have then a file in which for each pair of lines, the first one is the
#filename and the second one is the header, of wich the last characters after the ':'
#are the associated barcode. You can edit this file elsewhere and use it to get the
#barcodes associated for each sample and then paste them in the BarcodeSequences field
#of the mapping file. Pay attention to the correct order of file names!!

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/1_merge_and_trim.sh

2_import.sh

nano scripts/2_import.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --account=strauss
#SBATCH --job-name=import_ITS
#SBATCH --time=8:00:00
#SBATCH --ntasks=1
#SBATCH -n 8
#SBATCH --mem=20g
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/2_import_q2_%j.out
#SBATCH -A strauss
date;hostname;pwd

################################################################################
#
# Imports reads into Qiime2 artifacts and builds visualizations 
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
cd features
rm -r *.qza

# ----------------Commands------------------------

#Import Data in qiime2 artifact
qiime tools import \
  --type EMPSingleEndSequences \
  --input-path . \
  --output-path trimmed-seqs.qza

qiime demux emp-single \
 --i-seqs trimmed-seqs.qza \
 --m-barcodes-column BarcodeSequence \
 --o-per-sample-sequences demultiplexed-seqs.qza \
 --m-barcodes-file .../blabla                     #INSERT PATH TO VALIDATED MAPPING FILE

# Visualizations
qiime demux summarize \
  --i-data demultiplexed-seqs.qza \
  --o-visualization demultiplexed-seqs.qzv

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/1_merge_and_trim.sh

3_dada2_single.sh

Second difference: DADA2 with different parameters

nano scripts/3_dada2_single.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --time=24:00:00
#SBATCH -N 1
#SBATCH -J denoise_single
#SBATCH -n 14                                                     #NUMBER OF CPUS PER TASK
#SBATCH --mem=40g                                                 #MEMORY PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/3_denoise_singles_q2_%j.out
#SBATCH -A strauss

date;hostname;pwd

################################################################################
#
# Build feature table required for further analysis
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# Housekeeping:
cd features

# ----------------Commands------------------------
 
qiime dada2 denoise-single \
  --i-demultiplexed-seqs demultiplexed-seqs.qza \
  --p-trim-left 1 \
  --p-trunc-len 0 \
  --o-representative-sequences rep-seqs.qza \
  --p-n-threads 0 \
  --o-table table.qza \
  --o-denoising-stats stats.qza \
  --verbose

qiime feature-table summarize \
  --i-table table.qza \
  --o-visualization table.qzv \
  --m-sample-metadata-file  ../blabla                     #INSERT PATH TO VALIDATED MAPPING FILE

qiime feature-table tabulate-seqs \
  --i-data rep-seqs.qza \
  --o-visualization rep-seqs.qzv

# Unload modules:
module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/3_dada2_single.sh

4_Taxonomy_UNITE.sh

Finally the phylogenetic affiliation using UNITE database. Similarly to what done before, we will use a pretrained Naive Bayes classifier. Therefore, if you want to classify against a different version, you will use the optional training script provided.

nano scripts/4_Taxonomy_UNITE.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --mem=50g
#SBATCH --time=72:00:00
#SBATCH -N 1
#SBATCH -n 12
#SBATCH -J taxonomy_UNITE
#SBATCH -o logs/4_taxonomy_UNITE_%j.out
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -A strauss

date;hostname;pwd

################################################################################
#
# Assign taxonomy using a pre-trained scikit classifier version 0.19.1 and UNITE v.12-2017
# 
################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
cd features
rm taxonomy.qza
rm taxa-bar-plots.tsv
rm taxonomy.qzv

# ----------------Commands------------------------

qiime feature-classifier classify-sklearn \
  --i-reads rep-seqs.qza \
  --o-classification taxonomy.qza \
  --i-classifier  /ufrc/strauss/blabla          #INSERT PATH TO YOUR PRETRAINED DATABASE 

qiime metadata tabulate \
  --m-input-file taxonomy.qza \
  --o-visualization taxonomy.qzv

qiime taxa barplot \
  --i-table table.qza \
  --i-taxonomy taxonomy.qza \
  --o-visualization taxa-bar-plots.qzv \
  --m-metadata-file ../blabla                     #INSERT PATH TO VALIDATED MAPPING FILE

# Unload modules:
module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/4_Taxonomy_UNITE.sh

And here’s the optgional training

nano scripts/opt_train_sklearn_UNITE.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --mem=30g
#SBATCH --time=24:00:00
#SBATCH -N 1
#SBATCH -J scikit_training
#SBATCH -D /ufrc/strauss/                         #PATH TO A DATABASE FOLDER OF YOUR CHOICE
#SBATCH -o logs/q2_scikit_train_%j.out
#SBATCH -A strauss
date;hostname;pwd

# ----------------Housekeeping--------------------
#rm SILVA_128_99_otus.qza
#rm SILVA_128_99_tax.qza
#rm SILVA_128_99_otus_515-926.qza
#rm SILVA_nb_99_V3-V4.qza

# ----------------Load Modules--------------------
module load qiime2/2017.11

# ---------------Commands-------------------------

qiime tools import \
  --type FeatureData[Sequence] \
  --output-path UNITE_99_2017.12_seqs.qza \
  --input-path  /ufrc/strauss/blabla  #INSERT PATH TO sh_refs_qiime_ver7_99_s_01.12.2017.fasta 

qiime tools import \
  --type FeatureData[Taxonomy] \
  --source-format HeaderlessTSVTaxonomyFormat \
  --output-path UNITE_99_2017.12_tax.qza \
  --input-path  /ufrc/strauss/blabla  #INSERT PATH TO sh_taxonomy_qiime_ver7_99_s_01.12.2017.txt 


qiime feature-classifier fit-classifier-naive-bayes \
  --i-reference-reads UNITE_99_2017.12_seqs.qza \
  --i-reference-taxonomy UNITE_99_2017.12_tax.qza \
  --o-classifier UNITE_99_2017.12_classifier.qza

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/opt_train_sklearn_UNITE.sh

5_FUNGUILD.sh

Metabolic predictions are done by assigning taxa to guilds. (https://github.com/UMNFuN/FUNGuild). The results are stored in two files: a file ending with guilds.txt and a guilds_unmatched.txt. There are no visualizations for that so they need to be imported and visualized elsewhere (i.e. STAMP, Tableau, R, Excel)

nano scripts/5_FUNGUILD.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

##SBATCH -A strauss
#SBATCH -J FunGuild
#SBATCH -N 1
#SBATCH --time=72:00:00
#SBATCH --mem=25g                                                         #TOTAL RAM PER TASK       
#SBATCH -n 8                                                                #NUMBER OF CPUS PER TASK
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/ITS  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/5_Funguild_%j.out                                   #PATH OF LOG FILE

date;hostname;pwd

# ----------------Housekeeping--------------------
rm -r Funguild
mkdir Funguild
cd Funguild

# ----------------Load Modules--------------------
module load qiime2

# ---------------Commands-------------------------
qiime tools export \
  --input-path ../features/table.qza \
  --output-path exported-table

qiime tools export \
  --input-path ../features/taxonomy.qza \
  --output-path exported-taxonomy

module unload qiime2
module load qiime/1.9.1

biom convert \
  -i exported-table/feature-table.biom \
  -o feature-json.biom \
  --table-type="OTU table" \
  --to-json

sed -i s/Taxon/taxonomy/ exported-taxonomy/taxonomy.tsv | sed -i s/Feature\ ID/FeatureID/ exported-taxonom$

biom add-metadata \
  -i feature-json.biom \
  -o feature_w_tax.biom \
  --observation-metadata-fp exported-taxonomy/taxonomy.tsv \
  --observation-header FeatureID,taxonomy \
  --sc-separated taxonomy

filter_samples_from_otu_table.py \
  -i feature_w_tax.biom \
  -o filtered-table.biom \
  -n 1

filter_taxa_from_otu_table.py \
  -i filtered-table.biom \
  -o table_wo_chl_mit.biom \
  -n D_2__Chloroplast,D_4__Mitochondria
  
biom convert \
  -i table_wo_chl_mit.biom \
  -o fungi_table.txt \
  --to-tsv \
  --header-key taxonomy
  
sed -i s/"#OTU ID"/"OTU ID"/ fungi_table.txt
sed -i '1d' fungi_table.txt 

wget -O Funguild.py https://raw.githubusercontent.com/UMNFuN/FUNGuild/master/Guilds_v1.1.py

python3 Funguild.py -otu fungi_table.txt -db fungi -m -u

module unload qiime

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/5_FUNGUILD.sh

Merged kingdoms

Now it’s time to merge the taxonomy tables and the feature tables of 16S and ITS into one single table. Then, also the representative sequences obtained by the DADA2 output will be merged. Be careful with the mapping files, be sure that they all have the same number and order of samples!

cd merged
mkdir raw_seqs
mkdir logs
mkdir scripts

1_merge_kingdoms.sh

nano scripts/1_merge_kingdoms.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -J merge_kingdoms
#SBATCH --time=1:00:00
#SBATCH --ntasks=1
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/merged  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/1_merge_kingdoms_%j.out
#SBATCH -A strauss

date;hostname;pwd

################################################################################
#
# This script will merge the ITS and 16S table and taxonomy artifacts 
# 
#################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ------------------Commands----------------------
cp ../ITS/features/table.qza table_ITS.qza
cp ../ITS/features/taxonomy.qza taxonomy_ITS.qza
cp ../ITS/features/rep-seqs.qza repseqs_ITS.qza
cp ../16S/features/table.qza table_16S.qza
cp ../16S/features/taxonomy.qza taxonomy_16S.qza
cp ../16S/features/rep-seqs.qza repseqs_16S.qza

qiime feature-table merge \
  --i-tables table_16S.qza \
  --i-tables table_ITS.qza \
  --p-overlap-method error_on_overlapping_feature \
  --o-merged-table table.qza

qiime feature-table merge-taxa \
  --i-data taxonomy_16S.qza \
  --i-data taxonomy_ITS.qza \
  --o-merged-data taxonomy.qza

qiime feature-table merge-seqs \
 --i-data repseqs_16S.qza \
 --i-data repseqs_ITS.qza \
 --o-merged-data rep-seqs.qza

qiime feature-table summarize \
 --i-table table.qza \
 --o-visualization table.qzv \
 --m-sample-metadata-file ../blabla                       #INSERT PATH TO VALIDATED MAPPING FILE

qiime tools export \
  --input-path taxonomy.qza \
  --output-path .

sed -i s/Taxon/taxonomy/ taxonomy.tsv | sed -i s/Feature\ ID/FeatureID/ taxonomy.tsv

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/opt_train_sklearn_UNITE.sh

2_to_biom_and_beyond.sh

This script will now convert the tables into Phyloseq-readable files and produce also normalized tables using the DESEq2 algorithm (http://genomebiology.com/2014/15/12/550). For why this is better than rarefaction, please refer to the Waste not, want not paper (https://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1003531)

Watch out: in order to obtain correct filtering

nano scripts/2_to_biom_and_beyond.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH --mem=20g
#SBATCH --time=8:00:00
#SBATCH -N 1
#SBATCH -J q2_to_biom
#SBATCH -o logs/2_q2_to_biom_%j.out
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/merged  #PATH OF YOUR WORKING FOLDER
#SBATCH -A strauss

date;hostname;pwd

##################################################################################
#
# Filters low frequency features, and unwanted taxa, exports to Biom JSON and
# normalizes tables using CSS and DESeq2 algorithms
#
##################################################################################

# ----------------Load Modules--------------------
module load qiime2

# ----------------Housekeeping--------------------
rm -r biom
mkdir features
mv  *.qza features/
mv taxonomy.tsv features/taxonomy.tsv
cd features

# ------------------Commands----------------------

qiime tools export \
  --input-path table.qza \
  --output-path ../biom

qiime tools export \
  --input-path taxonomy.qza \
  --output-path ../biom

module unload qiime2
module load qiime/1.9.1

cd ../biom

biom convert \
  -i feature-table.biom \
  -o feature-json.biom \
  --table-type="OTU table" \
  --to-json

sed -i s/Taxon/taxonomy/ taxonomy.tsv | sed -i s/Feature\ ID/FeatureID/ taxonomy.tsv

biom add-metadata \
  -i feature-json.biom \
  -o feature_w_tax.biom \
  --observation-metadata-fp taxonomy.tsv \
  --observation-header FeatureID,taxonomy,Confidence \
  --sc-separated taxonomy --float-fields Confidence

filter_samples_from_otu_table.py \
  -i feature_w_tax.biom \
  -o filtered-table.biom \
  -n 1

filter_taxa_from_otu_table.py \
  -i filtered-table.biom \
  -o table_wo_chl_mit.biom \
  -n D_2__Chloroplast,D_4__Mitochondria

normalize_table.py \
  -i table_wo_chl_mit.biom \
  -a DESeq2 \
  --DESeq_negatives_to_zero \
  -o DESeq2_table.biom

biom add-metadata \
  -i DESeq2_table.biom \
  -o DESeq2_w_tax.biom \
  --observation-metadata-fp taxonomy.tsv \
  --observation-header FeatureID,taxonomy,Confidence \
  --sc-separated taxonomy --float-fields Confidence

normalize_table.py \
  -i table_wo_chl_mit.biom \
  -a CSS \
  -o CSS_table.biom

rm feature.tsv
rm feature-hdf5.biom

biom convert \
 -i table_wo_chl_mit.biom \
 -o feature-table.tsv \
 --to-tsv \
 --table-type "OTU table"

sed -i s/"#OTU ID"/FeatureID/ feature-table.tsv
sed -i '1d' feature-table.tsv

module unload qiime
module unload python

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/2_to_biom_and_beyond.sh

3_build_tree.sh

Finally, this script will use the merged sequences to build a new tree. Note that both this and the previous scripts can also be applied to the correspondent file having the same names in the 16S or the ITS folder, by changing the working directory

nano scripts/3_build_tree.sh
#!/bin/bash

# ----------------SLURM Parameters----------------

#SBATCH -J build_tree
#SBATCH --mem=20g
#SBATCH --time=8:00:00
#SBATCH --ntasks=1
#SBATCH -n 12
#SBATCH -D /ufrc/strauss/your_account/your_working_directory/merged  #PATH OF YOUR WORKING FOLDER
#SBATCH -o logs/3_q2_tree_%j.out
#SBATCH -A strauss

date;hostname;pwd

################################################################################
#
# Builds tree for further analysis and exports in .tre format
# 
################################################################################

# ----------------Housekeeping--------------------
cd biom
rm aligned-rep-seqs-filtered.qza
rm masked-aligned-rep-seqs-filtered.qza
rm unrooted-tree-filtered.qza
rm rooted-tree-filtered.qza
rm -r *.nwk

# ----------------Load Modules--------------------
module load qiime2

# ------------------Commands----------------------

qiime feature-table filter-seqs \
 --i-data ../features/rep-seqs.qza \
 --m-metadata-file feature-table.tsv \
 --p-no-exclude-ids \
 --o-filtered-data rep-seqs-filtered.qza

qiime alignment mafft \
  --i-sequences rep-seqs-filtered.qza \
  --p-n-threads 12 \
  --o-alignment aligned-rep-seqs-filtered.qza

qiime alignment mask \
  --i-alignment aligned-rep-seqs-filtered.qza \
  --o-masked-alignment masked-aligned-rep-seqs-filtered.qza

qiime phylogeny fasttree \
  --i-alignment masked-aligned-rep-seqs-filtered.qza \
  --o-tree unrooted-tree-filtered.qza

qiime phylogeny midpoint-root \
  --i-tree unrooted-tree-filtered.qza \
  --o-rooted-tree rooted-tree-filtered.qza

qiime tools export \
  --input-path rooted-tree-filtered.qza \
  --output-path .

module unload qiime2

date

Exit using ctrl + X and save with Y. Then do

sbatch scripts/3_build_tree.sh
LS0tCnRpdGxlOiAiUWlpbWUyIHdhbGt0aHJvdWdoIGZvciAxNlMsIElUUyBhbmQgYmV5b25kIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0aGVtZTogY29zbW8KICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwotLS0KI0ludHJvZHVjdGlvbgoKVGhpcyB0dXRvcmlhbCB3aWxsIGZvbGxvdyBtb3N0IHN0ZXBzIGZyb20gdGhlIE1vdmluZyBQaWN0dXJlcyBUdXRvcmlhbCB3aGljaCBtaWdodCBiZSBmb3VuZCBvbiB0aGUgcWlpbWUyIHdlYnNpdGUgKGh0dHBzOi8vZG9jcy5xaWltZTIub3JnLzIwMTguNi90dXRvcmlhbHMvbW92aW5nLXBpY3R1cmVzLykgYW5kIGludGVncmF0ZSBpdCB3aXRoIHNlcGFyYXRlIGluc3RydWN0aW9ucyBmb3IgdGhlIElUUyBzZXF1ZW5jZXMuIFRoZXNlIHNjcmlwdHMgYXJlIGJhc2VkIG9uIHRoZSBjdXJyZW50IHJlbGVhc2Ugb2YgcWlpbWUyICgyMDE4LjA2KSwgYnV0IGtlZXAgaW4gbWluZCB0aGF0IHRoZSBhdXRob3JzIHRlbmQgdG8gY2hhbmdlIHRoZSB0dXRvcmlhbCBwYWdlIGFuZCB1cGRhdGUgdGhlaXIgY29tbWFuZHMgYXQgZXZlcnkgbmV3IHJlbGVhc2Ugb2YgcWlpbWUyLiAKCllvdSBjYW4gYXNrIHRoZSBIaXBlcmdhdG9yIHN0YWZmIHRvIHVwZGF0ZSBxaWltZTIgb24gdGhlIHN1cHBvcnQgcGFnZSwgYnV0IHRoZXkgc2VlbSB0byBrZWVwIGl0IHByZXR0eSBjdXJyZW50OyBiZSBzdXJlIHRvIG1vZGlmeSB0aGUg4oCcbW9kdWxlIGxvYWTigJ0gY29tbWFuZCBhY2NvcmRpbmdseSBpbiBhbGwgc2NyaXB0cyBpZiB5b3Ugd2FudCB0byB1c2UgZGlmZmVyZW50IHZlcnNpb24uIE1vc3Qgb2YgdGhlIHNjcmlwdHMgYXJlIGJhc2VkIG9uIHRoZSBwcmV2aW91cyAxNlNyLVJOQSBQcmVwcm9jZXNzaW5nIFBpcGVsaW5lLgoKI1ByZWxpbWluYXJ5IHN0ZXBzOgpUbyBsb2dpbiBvbiBIaXBlcmdhdG9yIGZvbGxvdyB0aGUgcHJvY2VkdXJlcyByZXBvcnRlZCBhdCBodHRwczovL2hlbHAucmMudWZsLmVkdS9kb2MvR2V0dGluZ19TdGFydGVkI0Nvbm5lY3RpbmdfdG9fSGlQZXJHYXRvci4gSW4gdGhlIHNhbWUgcGFnZSwgdGhlcmUgYXJlIGFsc28gaW5zdHJ1Y3Rpb25zIGZvciBob3cgdG8gdXBsb2FkIGRhdGEgdG8gSGlwZXJnYXRvci4gSG93ZXZlciwgQkVGT1JFIHVwbG9hZGluZyB0aGUgZGF0YSwgY3JlYXRlIGEgZm9sZGVyIHN0cnVjdHVyZSB0aGF0IHdpbGwgYmUgdXNlZnVsIGZvciB5b3VyIHB1cnBvc2VzLiBJbiB0aGlzIGNhc2UsIEkgd2lsbCBiZSBzaG93aW5nIGJvdGggMTZTIGFuZCBJVFMgcGlwZWxpbmVzLCBhbmQgdGhlbiBob3cgdG8gbWVyZ2UgdGhlIHRhYmxlcy4gCgpBZnRlciBsb2dnaW5nIGluLCBuYXZpZ2F0ZSB0byB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IGFuZCBjcmVhdGUgdGhlIG5lY2Vzc2FyeSBzdWJmb2xkZXJzOgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KY2QgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeSAKbWtkaXIgMTZTCgpta2RpciBJVFMKCm1rZGlyIG1lcmdlZApgYGAKCgpJZiB5b3Ugd2FudCB0byBrbm93IHdobydzIGN1cnJlbnRseSB3b3JraW5nIG9uIGhpcGVyZ2F0b3IsIG9yIGlmIHlvdSB3YW50IHRvIGNoZWNrIGhvdyB5b3VyIGpvYiBpcyBwZXJmb3JtaW5nLCB5b3UgY2FuIGVudGVyIHRoaXMgY29tbWFuZDoKYGBge2Jhc2ggZXZhbD1GQUxTRX0Kd2F0Y2ggc3F1ZXVlIC1BIHN0cmF1c3MgLU8gam9iaWQ6MTAsdXNlcm5hbWUsbmFtZSxwYXJ0aXRpb24sc3RhdGU6MTAscmVhc29uOjEwLGNvcmVzLGdyZXM6MTAsdHJlczozMCx0aW1ldXNlZDoxMApgYGAKClRyeSBrZWVwIHRoZSBzdW1zIG9mIHRoZSBhbGxvY2F0ZWQgcmVzb3VyY2VzIGxvd2VyIHRoYW4gdGhlIGFjY291bnQgbGltaXRzOiBzb21lIGJhdGNoZXMgbWF5IGp1c3Qgd2FpdCBmb3IgdGhlIGV4Y2VzcyByZXNvdXJjZXMgdW50aWwgZnJlZSwgb3RoZXJzIHdpbGwganVzdCBicmVhayB0aGUgY3VycmVudGx5IHJ1bm5pbmcgYmF0Y2hlcy4gVG8gZXhpdCB0aGUgYWN0aXZpdHkgbW9uaXRvciBwcmVzcyBgY3RybCArIGNgLgoKIzE2UyBwaXBlbGluZQoKIyMwX3NldHVwLnNoCkZpcnN0IHRoaW5ncyBmaXJzdDogb25jZSB5b3UgaGF2ZSB5b3VyIGRlc2lnbmVkIHdvcmtpbmcgZm9sZGVyLCBtb3ZlIHlvdXIgcmF3IHNlcXVlbmNlcyBpbnRvIGEgYHJhd19zZXFzYCBkaXJlY3RvcnkgY3JlYXRlZCB0aGVyZWluLiBTZWNvbmRseSwgaXQgaXMgdXNlZnVsIHRvIGhhdmUgYSBzaW5nbGUgZm9sZGVyIG5hbWVkIGBzY3JpcHRzYCBmcm9tIHdoZXJlIHRvIGVkaXQgYW5kIGxhdW5jaCB5b3VyIGJhc2ggY29tbWFuZHMuIEFsbCBzY3JpcHRzIHdpbGwgYWxzbyBuZWVkIHRoZSBgbG9nc2AgZGlyZWN0b3J5IHdoaWNoIHlvdSBzaG91bGQgY3JlYXRlIG1hbnVhbGx5LCBpbiBvcmRlciBmb3IgeW91ciBjb21tYW5kcyB3aWxsIHByb2R1Y2UgdGhlaXIgbG9nZmlsZSBmb3IgYmFja3RyYWNlLgoKICAgIE5PVEU6IGNvbnRyYXJpbHkgdG8gcWlpbWUxLCBxaWltZTIgZG9lc27igJl0IG5lZWQgKHdlbGwsIGl0IHdvbuKAmXQgYWN0dWFsbHkgYWNjZXB0KSB1bmNvbXByZXNzZWQgZmFzdHEgZmlsZXMuIERvbuKAmXQgYGd1bnppcGAgdGhlbS4gCiAgICBOT1RFMjogdGhlc2Ugc2NyaXB0cyB3b3JrIG9ubHkgZm9yIGFscmVhZHkgZGVtdWx0aXBsZXhlZCBwYWlyZWQgc2VxdWVuY2VzLiBJZiB5b3UgaGF2ZSBtdWx0aXBsZXhlZCBzZXF1ZW5jZXMgb3Igc2luZ2xlIHJlYWRzIHlvdSBzaG91bGQgaGVhZCB0byB0aGUgcWlpbWUyIHdlYnNpdGUgYW5kIGFkanVzdCB0aGUgcGFyYW1ldGVycyBvZiBhbGwgc2NyaXB0cyBhY2NvcmRpbmdseS4KCiAgICAqSU1QT1JUQU5UKjogYmVmb3JlIGdvaW5nIG9uIHdpdGggdGhlIHNjcmlwdHMgbWFrZSBzdXJlIHRoZXJlIGFyZSBubyBkdXBsaWNhdGVzIGluIHRoZSBzYW1wbGUgZmlsZSBuYW1lcyAoaS5lLiB0aGUgcGFydCBvZiB0aGUgZmlsZSBuYW1lIHRoYXQgaXMgYmVmb3JlIGBfUjFfYCBvciBgX1IyX2ApISEgQ2hhbmdlIGZpbGUgbmFtZXMgYWNjdXJhdGVseSBhbmQgdGhlbiBwcm9jZWVkIHdpdGggdGhlIG5leHQgc2NyaXB0LgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KY2QgMTZTCm1rZGlyIHJhd19zZXFzCm1rZGlyIGxvZ3MKbWtkaXIgc2NyaXB0cwpgYGAKCk5vdyBtb3ZlIHlvdXIgY29tcHJlc3NlZCBzZXF1ZW5jZSBmaWxlcyBpbiB0aGUgYHJhd19zZXFzYCBkaXJlY3RvcnkgZm9sbG93aW5nIHRoZSBpbnN0cnVjdGlvbnMgZnJ0b20gdGhlIEhpcGVyZ2F0b3Igd2lraSBwYWdlLiBUaGVuIHN0YXJ0IHdyaXRpbmcgdGhlIGZpcnN0IGJhc2ggc2NyaXB0LCB1c2luZyAKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy8wX3NldHVwLnNoCmBgYCAKWW91IHdpbGwgYmUgcHJvbXB0ZWQgd2l0aCBhIHRleHQgZWRpdG9yIHdoZXJlIHlvdSBzaG91bGQgY29weS1wYXN0ZSB0aGUgZm9sbG93aW5nOgoKYGBge2Jhc2ggZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiMgLS0tLS0tLS0tLS0tLS0tLVNMVVJNIFBhcmFtZXRlcnMtLS0tLS0tLS0tLS0tLS0tCgojU0JBVENIIC1BIHN0cmF1c3MKI1NCQVRDSCAtSiBzZXR1cAojU0JBVENIIC1OIDEKI1NCQVRDSCAtRCAvdWZyYy9zdHJhdXNzL3lvdXJfYWNjb3VudC95b3VyX3dvcmtpbmdfZGlyZWN0b3J5LzE2UyAgI1BBVEggT0YgWU9VUiBXT1JLSU5HIEZPTERFUgojU0JBVENIIC1vIGxvZ3MvMF9zZXR1cF8lai5vdXQJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgU2V0dXAgZGF0YSBkaXJlY3RvcnkgYW5kIGNvcHkgcmF3X3NlcXMgY29udGVudHMKIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyAtLS0tLS0tLS0tLS0tLS0tSG91c2VrZWVwaW5nLS0tLS0tLS0tLS0tLS0tLS0tLS0Kcm0gLXJmIGRhdGEKbWtkaXIgZGF0YQpta2RpciBkYXRhL3Jhd19kYXRhCgojIC0tLS0tLS0tLS0tLS0tLS0tLUNvbW1hbmRzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBJZiBzZXF1ZW5jZXMgYXJlIGluZGl2aWR1YWwgZGlyZWN0b3JpZXMgKGlmIG5vdCwgY29tbWVudCB0aGlzIG91dCk6CmZvciBkaXIgaW4gcmF3X3NlcXMvKjsgZG8KICAgIGNwICRkaXIvKiBkYXRhL3Jhd19kYXRhLy4KZG9uZSAKCiMgRml4IG5hbWVzOiB0aGlzIGRlcGVuZHMgb2YgY291cnNlIG9uIGhvdyB5b3VyIGZpbGVzIGFyZSBuYW1lZC4gQ0hFQ0sgVEhFTSEKZm9yIGZpbGUgaW4gZGF0YS9yYXdfZGF0YS8qLmd6OyBkbwogICAgbXYgJGZpbGUgJHtmaWxlL1N0cmF1c3M/LS99OwogICAgbXYgJGZpbGUgJHtmaWxlL1N0cmF1c3M/Py0vfTsKICAgIG12ICRmaWxlICR7ZmlsZS9TdHJhdXNzPz8/LS99Owpkb25lCgpkYXRlCmBgYApFeGl0IHVzaW5nIGN0cmwgKyBYIGFuZCBzYXZlIHdpdGggWS4gVGhlbiBkbwoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy8wX3NldHVwLnNoCmBgYAojIzFfaW1wb3J0LnNoCipfRXN0aW1hdGVkIHRpbWU6IGZldyBtaW51dGVzXyoKCk5vdyBpdCBpcyB0aW1lIHRvIGltcG9ydCBvdXIgc2VxdWVuY2VzLiBUaGlzIHNjcmlwdCB3aWxsIGNyZWF0ZSBhIFFpaW1lMiBhcnRpZmFjdCB3aGljaCBjb250YWlucyB0aGUgc2VxdWVuY2VzIGRhdGEgKHRoZXkgY2FsbCBpdCBGZWF0dXJlRGF0YVtTZXF1ZW5jZV0pLiBUaGlzIHNjcmlwdCBkaWZmZXJzIGZyb20gdGhlIE1vdmluZyBQaWN0dXJlcyBUdXRvcmlhbCwgYmVjYXVzZSBpdCBpcyB0YWlsb3JlZCBmb3IgcGFpcmVkIGVuZCBkZW11bHRpcGxleGVkIHNlcXVlbmNlcy4gCgpRaWltZTIgLnF6YSBhcnRpZmFjdHMgYXJlIGFjdHVhbGx5IGNvbXByZXNzZWQgZmlsZXMgd2hpY2ggY29udGFpbiBhIHR5cGljYWwgcWlpbWUxIG91dHB1dCBmaWxlICh3aGljaCBtaWdodCBiZSBhIGJpb20gdGFibGUsIGEgdGF4b25vbXkgdGFibGUgb3IgYSBmYXN0YSBmaWxlKSBoaWRkZW4gaW4gc29tZSBzdWJmb2xkZXJzIGFuZCBhY2NvbXBhbmllZCBieSB0aGUgZmlsZXMgbmVjZXNzYXJ5IGZvciBnZW5lcmF0aW5nIHRoZSB2aXN1YWxpemF0aW9uLiBWaXN1YWxpemF0aW9uIGFyZSB0aGUg4oCcYmlnIHRoaW5n4oCdIG9mIHFpaW1lMiwgd2hpY2ggYWxsb3dzIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBhIGdyYXBoaWMgaW50ZXJmYWNlIGFzIHdlbGwsIGFuZCBhbGxvdyB0byB2aWV3IHRoZSBkYXRhIGdyYXBoaWNhbGx5IHdpdGggaW50ZXJhY3RpdmUgcGxvdHMgYW5kIHRhYmxlcy4gCgpUaGUgc2NyaXB0IHByb2R1Y2VzIGEgdmlzdWFsaXphdGlvbiB3aGljaCBzdW1tYXJpemVzIHRoZSBxdWFsaXR5IGRhdGEgYW5kIHRoZSBsZW5ndGhzIG9mIHlvdXIgcmVhZHMgKGkuZS4gc2ltaWxhciB0byB0aGUgc3RhdHMudHh0IHByb2R1Y2VkIGJ5IHRoZSBVU0VBUkNIIHBpcGVsaW5lIGNvbW1hbmRzKS4gVGhpcyBjYW4gYmUgdmlld2VkIGJ5IGxvYWRpbmcgaXQgb24gdGhlIGh0dHBzOi8vdmlldy5xaWltZTIub3JnIHdlYnNpdGUuCgogICAgTk9URTogSGlwZXJHYXRvciBkb2VzIG5vdCBoYXZlIGEgdmlzdWFsIGludGVyZmFjZSwgYXQgbGVhc3QgaW4gc3RyYXVzcyBwYXJ0aXRpb24uIFRoZXJlZm9yZSwgaXQgaXMgbGlrZWx5IHRoYXQgd2hlbiB0aGUgc2NyaXB0cyB3aWxsIGxvb2sgZm9yIG1hdHBsb3RsaWIgdG8gYnVpbGQgdGhlIHZpc3VhbGl6YXRpb24gZmlsZSwgdGhleSB3b3VsZCByZXR1cm4gYW4gZXJyb3IuIAogICAgClRvIGF2b2lkIHRoYXQsIHNpbXBseSB3cml0ZSBhbiBlbXB0eSBmaWxlIGluIHlvdXIgY29uZmlnIHdpdGgKYGBge2Jhc2ggZXZhbD1GQUxTRX0gICAgCm5hbm8gfi8uY29uZmlnL21hdHBsb3RsaWIvbWF0cGxvdGxpYnJjCmBgYApZb3Ugd2lsbCB0aGVuIGJlIHByb21wdGVkIGFuIGVtcHR5IHBhZ2UgaW4gd2hpY2ggeW91IHdpbGwgd3JpdGUgdGhpcyBsaW5lIG9ubHkKYGBge2Jhc2ggZXZhbD1GQUxTRX0gICAgCmJhY2tlbmQgOiBhZ2cKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzFfaW1wb3J0LnNoCmBgYAoKQW5kIGNvcHlwYXN0ZSB0aGUgZm9sbG93aW5nCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLUEgc3RyYXVzcwojU0JBVENIIC1KIHEyX2ltcG9ydAojU0JBVENIIC0tdGltZT0yOjAwOjAwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjTWF4aW11bSBudW1iZXIgb2YgaG91cnMKI1NCQVRDSCAtTiAxICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI051bWJlciBvZiBub2RlcwojU0JBVENIIC0tbWVtPTEwZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjQWxsb2NhdGVkIFJBTQojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvMTZTICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLW8gbG9ncy8xX3EyX2ltcG9ydF8lai5vdXQJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgSW1wb3J0IGZhc3RxLmd6IGZpbGVzIGludG8gYSAucXphIGZpbGUKIyAKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS0tSG91c2VrZWVwaW5nLS0tLS0tLS0tLS0tLS0tLS0tLS0tCnJtIC1yIGRlbXV4Ki5xKgpjZCBkYXRhCgojIC0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKI0ltcG9ydCBEYXRhIGluIHFpaW1lMiBhcnRpZmFjdApxaWltZSB0b29scyBpbXBvcnQgXAogIC0tdHlwZSAnU2FtcGxlRGF0YVtQYWlyZWRFbmRTZXF1ZW5jZXNXaXRoUXVhbGl0eV0nIFwKICAtLWlucHV0LXBhdGggcmF3X2RhdGEgXAogIC0taW5wdXQtZm9ybWF0IENhc2F2YU9uZUVpZ2h0U2luZ2xlTGFuZVBlclNhbXBsZURpckZtdCBcCiAgLS1vdXRwdXQtcGF0aCBkZW11eC1wYWlyZWQtZW5kLnF6YQoKIyBDcmVhdGUgRGF0YSBWaXN1YWlsaXphdGlvbnMKIyBBVFRFTlRJT046IGlmIHlvdXIgZGVtdXggZ2l2ZSB5b3UgImludmFsaWQgRElTUExBWSB2YXJpYWJsZSBlcnJvciIgaXQncyBiZWNhdXNlIHlvdSBkb24ndCBoYXZlIGdyYXBoaWMgaW50ZXJmYWNlLgojIFRvIHNvbHZlIGl0IGNyZWF0ZSBhIGZpbGUgdXNpbmcgbmFubyB+Ly5jb25maWcvbWF0cGxvdGxpYi9tYXRwbG90bGlicmMKIyBBbmQgd3JpdGUgdGhlIGZvbGxvd2luZwojIGJhY2tlbmQgOiBhZ2cKCnFpaW1lIGRlbXV4IHN1bW1hcml6ZSBcCiAgLS1pLWRhdGEgZGVtdXgtcGFpcmVkLWVuZC5xemEgXAogIC0tby12aXN1YWxpemF0aW9uIGRlbXV4LXBhaXJlZC1lbmQucXp2CgojIFVubG9hZCBtb2R1bGVzOgptb2R1bGUgdW5sb2FkIHFpaW1lMgoKZGF0ZQoKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0Kc2JhdGNoIHNjcmlwdHMvMV9pbXBvcnQuc2gKYGBgCgpBZnRlciB0aGUgc2NyaXB0IGZpbmlzaGVzLCBsb2FkIHRoZSBkZW11eC1wYWlyZWQtZW5kLnF6diBmaWxlIGluIHRoZSBodHRwczovL3ZpZXcucWlpbWUyLm9yZyAgd2Vic2l0ZS4gWW91IHdpbGwgc2VlIHdoZW4gdGhlIHF1YWxpdHkgb2YgeW91ciByZWFkcyBkZWdlbmVyYXRlcyB0aHJvdWdoIGFuIGludGVyYWN0aXZlIGJveC1wbG90LiBUaHJvdWdoIHRoaXMgYm94LXBsb3QsIHlvdSBjYW4gZGV0ZXJtaW5lIGF0IHdoaWNoIGxlbmd0aCB5b3Ugd291bGQgdHJ1bmNhdGUgdGhlIGZvcndhcmQgYW5kIHRoZSByZXZlcnNlIHJlYWRzIHJlc3BlY3RpdmVseS4gWW91IHdpbGwgbmVlZCB0aGVzZSB2YWx1ZXMgZm9yIHRoZSBuZXh0IHNjcmlwdC4gVGhlIGlkZWEgaXMsIG9mIGNvdXJzZSwgdG8gZmluZCBhIGNvbXByb21pc2UgYmV0d2VlbiByZXRhaW5pbmcgdGhlIGhpZ2hlciBudW1iZXIgb2YgcmVhZHMgYW5kIHJldGFpbmluZyB0aGUgYmVzdCBxdWFsaXR5IG9mIHRoZW0uIAoKIVtdKGZpZ3VyZXMvcXVhbGl0eS5KUEcpCgojIzJfZGFkYTIuc2gKRXN0aW1hdGVkIHRpbWU6IG1hbnkgaG91cnMKVGhlIG5leHQgc3RlcCBpcyBkZXJlcGxpY2F0aW9uLiBUaGlzIHNjcmlwdCB1c2VzIHRoZSBEQURBMiBSIHBhY2thZ2UgKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvbm1ldGguMzg2OSkgd2hpY2ggaXMgaW1wbGVtZW50ZWQgaW4gcWlpbWUyIHBpcGVsaW5lLiAKCiAgICBOb3RlOiBGb3IgYSBjb21wYXJpc29uIG9mIERBREEyIGFtcGxpY29uIHNlcXVlbmNlIHZhcmlhbnRzIGNhbGxpbmcgYWdhaW5zdCB0aGUgY3VycmVudCBPVFUgcGlja2luZyBhbGdvcml0aG0gKDIwMTYpIGNoZWNrIGh0dHBzOi8vYmVuampuZWIuZ2l0aHViLmlvL2RhZGEyL1NvdEEuaHRtbC4gCgpBY2N1cmFjeTogREFEQTLigJlzIGNydWNpYWwgYWR2YW50YWdlIGlzIHRoYXQgaXQgdXNlcyBtb3JlIG9mIHRoZSBkYXRhLiBUaGUgREFEQTIgZXJyb3IgbW9kZWwgaW5jb3Jwb3JhdGVzIHF1YWxpdHkgaW5mb3JtYXRpb24sIHdoaWNoIGlzIGlnbm9yZWQgYnkgYWxsIG90aGVyIG1ldGhvZHMgYWZ0ZXIgZmlsdGVyaW5nLiBUaGUgREFEQTIgZXJyb3IgbW9kZWwgaW5jb3Jwb3JhdGVzIHF1YW50aXRhdGl2ZSBhYnVuZGFuY2VzLCB3aGVyZWFzIG1vc3Qgb3RoZXIgbWV0aG9kcyB1c2UgYWJ1bmRhbmNlIHJhbmtzIGlmIHRoZXkgdXNlIGFidW5kYW5jZSBhdCBhbGwuIFRoZSBEQURBMiBlcnJvciBtb2RlbCBpZGVudGlmaWVzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHNlcXVlbmNlcywgZWcuIEEtPkMsIHdoZXJlYXMgb3RoZXIgbWV0aG9kcyBtZXJlbHkgY291bnQgdGhlIG1pc21hdGNoZXMuIERBREEyIGNhbiBwYXJhbWV0ZXJpemUgaXRzIGVycm9yIG1vZGVsIGZyb20gdGhlIGRhdGEgaXRzZWxmLCByYXRoZXIgdGhhbiByZWx5aW5nIG9uIHByZXZpb3VzIGRhdGFzZXRzIHRoYXQgbWF5IG9yIG1heSBub3QgcmVmbGVjdCB0aGUgUENSIGFuZCBzZXF1ZW5jaW5nIHByb3RvY29scyB1c2VkIGluIHlvdXIgc3R1ZHkuCgpQZXJmb3JtYW5jZTogREFEQTLigJlzIGNvbXB1dGF0aW9uYWwgc2NhbGluZyBnYWlucyBjb21lIGZyb20gdGhlIGZhY3QgdGhhdCBpdCBpbmZlcnMgc2VxdWVuY2VzIGV4YWN0bHkgcmF0aGVyIHRoYW4gY29uc3RydWN0aW5nIE9UVXMuIERlIG5vdm8gT1RVcyBjYW5ub3QgYmUgY29tcGFyZWQgYWNyb3NzIHNhbXBsZXMgdW5sZXNzIGFsbCBzYW1wbGVzIHdlcmUgcG9vbGVkIGR1cmluZyBPVFUgY29uc3RydWN0aW9uLiBIb3dldmVyLCBleGFjdCBzZXF1ZW5jZXMgYXJlIGNvbXBhcmFibGUgYWNyb3NzIHNhbXBsZXMsIGFzIGV4YWN0IHNlcXVlbmNlcyBhcmUgY29uc2lzdGVudCBsYWJlbHMuIFRodXMgREFEQTIgY2FuIGFuYWx5emUgZWFjaCBzYW1wbGUgaW5kZXBlbmRlbnRseSwgcmVzdWx0aW5nIGluIGxpbmVhciBzY2FsaW5nIHdpdGggc2FtcGxlIG51bWJlciBhbmQgdHJpdmlhbCBwYXJhbGxlbGl6YXRpb24uCgpJdCBpcyBleHRyZW1lbHkgYWNjdXJhdGUgYW5kIGxvd2VycyB0aGUgZnJhY3Rpb24gb2YgZmFsc2UgcG9zaXRpdmVzLiBJbiBvdXIgcHJldmlvdXMgY29tcGFyaXNvbnMgYWdhaW5zdCB0aGUgVVNFQVJDSCBjbHVzdGVyaW5nIG1ldGhvZCwgREFEQTIgd2FzIHNob3duIHRvIGJldHRlciBkaXNjZXJuIHRoZSBzYW1wbGVzIGFuZCByZXN1bHQgaW4gYSBtdWNoIGhpZ2hlciBkaXZlcnNpdHkuIFRlY2huaWNhbGx5LCBpdCByZWxpZXMgb24gaW5mZXJlbmNlIG92ZXIgc2VxdWVuY2VzIHJhdGhlciB0aGFuIE9UVSBjbHVzdGVyaW5nLCBhbmQgdGhpcyBpcyB3aHkgaXQgaXMgYWJsZSB0byBiZXR0ZXIgZGlzY2VybiBhIGdlbmV0aWMgdmFyaWF0aW9uIGZyb20gYSBkaWZmZXJlbnQgc3BlY2llcyAoc2VlIHdlYnNpdGUgZm9yIG1vcmUgaW5mbykuIAoKVGhlIHNjcmlwdCB3aWxsIGNyZWF0ZSBhIG5ldyBmb2xkZXIgY2FsbGVkIGZlYXR1cmVzIGFuZCBwZXJmb3JtIGl0cyBhbmFseXNpcyB0aGVyZSB3aGljaCBpbmNsdWRlOiBkZW5vaXNpbmcgb2YgdGhlIHNlcXVlbmNlcywgZGVyZXBsaWNhdGlvbiwgY2hpbWVyYSByZW1vdmFsIGFsbCBpbiBvbmUgc3RlcC4gVGhlIHNjcmlwdCB1c2VzIGEgcGFyYWxsZWxpemVkIHZlcnNpb24gb2YgdGhlIERBREEyIGFsZ29yaXRobSwgc3BsaXR0aW5nIHRoZSB3b3JrcyBvbiAxMiBjb3Jlcy4gVGhlIG1vcmUgdGhlIGNvcmVzLCB0aGUgc2hvcnRlciB0aGUgdGltZSBpdCB3aWxsIHRha2UuIEl0IHdpbGwgcmVzdWx0IGluIGEgdGFibGUucXphIGZpbGUsIHdoaWNoIGNvbnRhaW5zIGFuIGF0eXBpY2FsIGJpb20gdGFibGUsIHF1YXNpLUhERjUsIGFuZCBhIHJlcC1zZXFzLnF6YSBmaWxlLCBmcm9tIHdoaWNoIHlvdSBjYW4gZXh0cmFjdCBhIHRoZSBmYXN0YSBmaWxlIGNvbnRhaW5pbmcgcmVwcmVzZW50YXRpdmUgc2VxdWVuY2VzLiBCb3RoIG9mIHRoZW0gd2lsbCBiZSB1c2VkIGluIHRoZSBmb2xsb3dpbmcgc2NyaXB0cy4gCgogICAgTk9URTogaW4gb3JkZXIgdG8gdHJ1bmNhdGUgbG93IHF1YWxpdHkgcmVnaW9ucyBhdCB0aGUgZW5kIG9mIHRoZSBzZXF1ZW5jZXMsIHRoZSBzY3JpcHQgbmVlZHMgeW91IHRvIHNwZWNpZml5IHRoZSBsZW5ndGggb2YgZWFjaCBzZXF1ZW5jZSAoZncgYW5kIHJldikgaW4gbnVtYmVyIG9mIGJhc2VzLiBVc2UgdGhlIHF1YWxpdHkgcGxvdHMgZnJvbSB0aGUgLnF6diBmaWxlIHByb2R1Y2VkIGluIHRoZSBwcmV2aW91cyBzdGVwIHRvIGRldGVybWluZSBzdWNoIG51bWJlciBhbmQgaW5zZXJ0IGl0IGluIHBsYWNlIG9mIHRoZSB0d28gcGxhY2Vob2xkZXJzIHNwZWNpZmllZC4KCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpuYW5vIHNjcmlwdHMvMl9kYWRhMi5zaApgYGAKCmBgYHtiYXNoIGV2YWw9RkFMU0V9CiMhL2Jpbi9iYXNoCgojIC0tLS0tLS0tLS0tLS0tLS1TTFVSTSBQYXJhbWV0ZXJzLS0tLS0tLS0tLS0tLS0tLQoKI1NCQVRDSCAtQSBzdHJhdXNzCiNTQkFUQ0ggLUogcGFyX2RhZGEyCiNTQkFUQ0ggLU4gMQojU0JBVENIIC0tdGltZT0yNDowMDowMAojU0JBVENIIC0tbWVtPTQwZwkJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAJICAjVE9UQUwgUkFNIFBFUiBUQVNLCiNTQkFUQ0ggLW4gMTIJCQkJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI05VTUJFUiBPRiBDUFVTIFBFUiBUQVNLCiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS8xNlMgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtbyBsb2dzLzJfcTJfZGFkYTJfJWoub3V0CSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgRmlsdGVycyBwYWlyZWQtZW5kIHNlcXVlbmNlcyBiYXNlZCBvbiBxdWFsaXR5LCBtZXJnZXMgZGVyZXBsaWNhdGVzIHRoZW0gCiMgdXNpbmcgREFEQTIgYWxnb3JpdGhtLiBJbmNsdWRlcyBjaGltZXJhIHJlbW92YWwuCiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBxaWltZTIKCiMgLS0tLS0tLS0tLS0tLS0tLUhvdXNla2VlcGluZy0tLS0tLS0tLS0tLS0tLS0tLS0tCnJtIC1yIGZlYXR1cmVzCm1rZGlyIGZlYXR1cmVzCmNwIGRhdGEvZGVtdXgtcGFpcmVkLWVuZC5xemEgZmVhdHVyZXMvZGFkYTJpbnB1dC5xemEKY2QgZmVhdHVyZXMKCgojIC0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcWlpbWUgZGFkYTIgZGVub2lzZS1wYWlyZWQgXAogIC0taS1kZW11bHRpcGxleGVkLXNlcXMgZGFkYTJpbnB1dC5xemEgXAogIC0tcC1uLXRocmVhZHMgMCBcCiAgLS1wLXRydW5jLWxlbi1mIFwgICAgI0lOU0VSVCBOVU1CRVIgT0YgQkFTRVMgQkVGT1JFIFRIRSBGT1JXQVJEIFNMQVNIIEFORCBERUxFVEUgVEhJUyBJTlNUUlVDVElPTgogIC0tcC10cnVuYy1sZW4tciBcICAgI0lOU0VSVCBOVU1CRVIgT0YgQkFTRVMgQkVGT1JFIFRIRSBGT1JXQVJEIFNMQVNIIEFORCBERUxFVEUgVEhJUyBJTlNUUlVDVElPTgogIC0tby10YWJsZSB0YWJsZS5xemEgXAogIC0tby1kZW5vaXNpbmctc3RhdHMgc3RhdHMucXphIFwKICAtLW8tcmVwcmVzZW50YXRpdmUtc2VxdWVuY2VzIHJlcC1zZXFzLnF6YSAKCm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCgpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8yX2RhZGEyLnNoCmBgYAoKIyMzX2ZlYXR1cmVfdGFibGUuc2gJCl9Fc3RpbWF0ZWQgdGltZTogbWludXRlc18KClRoaXMgc2NyaXB0IHdpbGwgYnVpbGQgYSBmZWF0dXJlIHRhYmxlLCB3aGljaCBpcyBhIHNpbWlsYXIgY29uY2VwdCBvZiB0aGUgT1RVIHRhYmxlIGZyb20gcWlpbWUxLiBCZWZvcmUgYXBwbHlpbmcgdGhpcyBzY3JpcHQgaXQgaXMgaGlnaGx5IHJlY29tbWVuZGVkIHRvIGNoZWNrIHRoZSBtYXBwaW5nIGZpbGUsIHNpbmNlIGVycm9ycyBpbiBmaWxlIG5hbWVzIHdpbGwgYmUgY2FycmllZCBvbiB1bnRpbCB0aGUgZW5kIG9mIHRoZSBhbmFseXNpcy4gQSBnb29kIHRvb2wgdG8gdmFsaWRhdGUgcWlpbWUxIGFuZCBxaWltZTIgbWFwcGluZyBmaWxlcyBpcyB0aGUgS2VlbWVpIGFkZC1vbiBmb3IgZ29vZ2xlIHNwcmVhZHNoZWV0LCB3aGljaCBydW5zIGluIGNocm9tZSAoY2FuIGJlIGFkZGVkIGZyb20gdGhlIGNocm9tZSBzdG9yZSBodHRwOi8va2VlbWVpLnFpaW1lLm9yZykuIE9uY2UgaW5zdGFsbGVkLCB5b3UgbmVlZCB0byBvcGVuIGFuIGVtcHR5IGdvb2dsZSBzcHJlYWRzaGVldCwgdGhlbiBnbyB0byBhZGQtb24sIEtlZW1laSwgYW5kIHZhbGlkYXRlIHRoZSBtYXBwaW5nIGZpbGUgZm9yIHRoZSB2ZXJzaW9uIG9mIHFpaW1lIHJlcXVpcmVkLiBUaGUgcHJvY2VzcyBpcyBpbnRlcmFjdGl2ZSBhbmQgd2lsbCBndWlkZSB5b3UgdGhyb3VnaCBkdXBsaWNhdGUgdmFsdWVzLCBmb3JtYXR0aW5nIGlzc3VlcywgZXRjLiAKCkZpbmFsbHksIHRoZSBzY3JpcHQgd2lsbCBhbHNvIHByb2R1Y2UgdmlzdWFsaXphdGlvbiBvZiBib3RoIHRoZSBzZXF1ZW5jZSBmaWxlIChyZXAtc2Vxcy5xemEpIGFuZCBvZiB0aGUgZmVhdHVyZSB0YWJsZSAodGFibGUucXphKSwgd2hpY2ggd2lsbCBiZSB1c2VmdWwgZm9yIHRoZSBuZXh0IHN0ZXBzLiAKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy8zX2ZlYXR1cmVfdGFibGUuc2gJCmBgYAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CiMhL2Jpbi9iYXNoCgojIC0tLS0tLS0tLS0tLS0tLS1TTFVSTSBQYXJhbWV0ZXJzLS0tLS0tLS0tLS0tLS0tLQoKI1NCQVRDSCAtQSBzdHJhdXNzCQkKI1NCQVRDSCAtSiBxMl9mZWF0dGFiCiNTQkFUQ0ggLU4gMQojU0JBVENIIC0tdGltZT0yOjAwOjAwCQkJCiNTQkFUQ0ggLS1tZW09MTBnCQkJICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjVE9UQUwgUkFNIFBFUiBUQVNLCiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS8xNlMgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtbyBsb2dzLzNfcTJfZmVhdHVyZV90YWJsZV8lai5vdXQJICAgICAgICAgICAgICAgICAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgQnVpbGQgZmVhdHVyZSB0YWJsZSByZXF1aXJlZCBmb3IgZnVydGhlciBhbmFseXNpcwojIAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyAtLS0tLS0tLS0tLS0tLS0tTG9hZCBNb2R1bGVzLS0tLS0tLS0tLS0tLS0tLS0tLS0KbW9kdWxlIGxvYWQgcWlpbWUyCgojIEhvdXNla2VlcGluZzoKY2QgZmVhdHVyZXMKcm0gdGFibGUucXp2CnJtIHJlcC1zZXFzLnF6dgpybSByZWluZGV4ZWQtdGFibGUucXphCgojIC0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcWlpbWUgZmVhdHVyZS10YWJsZSBzdW1tYXJpemUgXAogIC0taS10YWJsZSB0YWJsZS5xemEgXAogIC0tby12aXN1YWxpemF0aW9uIHRhYmxlLnF6diBcCiAgLS1tLXNhbXBsZS1tZXRhZGF0YS1maWxlICAuLi9ibGFibGEgICAgIAkJI0lOU0VSVCBQQVRIIFRPIFZBTElEQVRFRCBNQVBQSU5HIEZJTEUKCnFpaW1lIGZlYXR1cmUtdGFibGUgdGFidWxhdGUtc2VxcyBcCiAgLS1pLWRhdGEgcmVwLXNlcXMucXphIFwKICAtLW8tdmlzdWFsaXphdGlvbiByZXAtc2Vxcy5xenYKCiMgVW5sb2FkIG1vZHVsZXM6Cm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCmBgYApFeGl0IHVzaW5nIGBjdHJsICsgWGAgYW5kIHNhdmUgd2l0aCBgWWAuIFRoZW4gZG8KYGBge2Jhc2gsIGV2YWw9RkFMU0V9CnNiYXRjaCBzY3JpcHRzLzNfZmVhdHVyZV90YWJsZS5zaAkKYGBgCiFbXShmaWd1cmVzL3RhYmxlLkpQRykKCiMjNF90YXhvbm9teS5zaAkKX0VzdGltYXRlZCB0aW1lOiBob3Vyc18KClRoaXMgc2NyaXB0IHByb3ZpZGVzIHRoZSB0YXhvbm9taWMgYXNzaWdubWVudHMgdG8geW91ciBzZXF1ZW5jZXMuIFRvIGRvIHNvLCBpdCB3aWxsIHVzZSBhIHByZS10cmFpbmVkIGRhdGFzZXQsIHdoaWNoIGlzIGEgc2VxdWVuY2UgZGF0YWJhc2UgaW5mZXJyZWQgdGhyb3VnaCB0aGUgYXBwbGljYXRpb24gb2YgdGhlIG5hw692ZSBCYXllcyBjbGFzc2lmaWVyLCBhbmQgdXNlIGEgbWFjaGluZSBsZWFybmluZyBhbGdvcml0aG0gdG8gYXNzaWduIHRoZSB0YXhvbm9teSBvZiB5b3VyIHNlcXVlbmNlIHRvIHRoYXQgY2xhc3NpZmllci4gVGhlcmVmb3JlLCBpdCByZXF1aXJlcyBoaWdoIGNvbXB1dGF0aW9uYWwgcG93ZXIsIGFuZCBmb3IgdGhpcyByZWFzb24gdGhlIHNjcmlwdCBhbGxvY2F0ZXMgbWFueSBwcm9jZXNzb3JzIGludG8gd2hpY2ggdGhlIHNjcmlwdCBpcyBwYXJhbGxlbGl6ZWQsIGFuZCBhIGhpZ2ggYW1vdW50IG9mIG1lbW9yeSBhcyB3ZWxsLiBUaGUgcWlpbWUyIHdlYnNpdGUgcHJvdmlkZXMgYSBjbGFzc2lmaWVyIGZvciBHcmVlbmdlbmVzIDEzXzggYW5kIGEgY2xhc3NpZmllciBmb3IgU0lMVkEgMTE5OyBiZSBjYXJlZnVsIHRvIGRvd25sb2FkIHRoZSBmdWxsIHNlcXVlbmNlcyBhbmQgbm90IHRoZSB0cnVuY2F0ZWQgc2VxdWVuY2VzIGZvciB0aGUgVjMgcmVnaW9uIG9ubHkuIApgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzRfdGF4b25vbXlfU0lMVkEuc2gJCQpgYGAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLUEgc3RyYXVzcwojU0JBVENIIC1KIHEyX3NjaWtpdF90YXgKI1NCQVRDSCAtTiAxCiNTQkFUQ0ggLS10aW1lPTcyOjAwOjAwCiNTQkFUQ0ggLS1tZW09MzBnCQkJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNUT1RBTCBSQU0gUEVSIFRBU0sJCQojU0JBVENIIC1uIDgJCQkJCSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI05VTUJFUiBPRiBDUFVTIFBFUiBUQVNLCiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS8xNlMgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtbyBsb2dzLzRfcTJfdGF4X1NJTFZBMTI4XyVqLm91dAkgICAgICAgICAgICAgICAgICAgICAgICAjUEFUSCBPRiBMT0cgRklMRQoKZGF0ZTtob3N0bmFtZTtwd2QKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMKIyBBc3NpZ24gdGF4b25vbXkgdXNpbmcgYSBwcmUtdHJhaW5lZCBzY2lraXQgY2xhc3NpZmllciB2ZXJzaW9uIDAuMTkuMQojIAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyAtLS0tLS0tLS0tLS0tLS0tTG9hZCBNb2R1bGVzLS0tLS0tLS0tLS0tLS0tLS0tLS0KbW9kdWxlIGxvYWQgcWlpbWUyCgojIC0tLS0tLS0tLS0tLS0tLS1Ib3VzZWtlZXBpbmctLS0tLS0tLS0tLS0tLS0tLS0tLQpjZCBmZWF0dXJlcwpybSB0YXhvbm9teS5xemEKcm0gdGF4YS1iYXItcGxvdHMudHN2CnJtIHRheG9ub215LnF6dgoKIyAtLS0tLS0tLS0tLS0tLS0tQ29tbWFuZHMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KcWlpbWUgZmVhdHVyZS1jbGFzc2lmaWVyIGNsYXNzaWZ5LXNrbGVhcm4gXAogIC0taS1yZWFkcyByZXAtc2Vxcy5xemEgXAogIC0tby1jbGFzc2lmaWNhdGlvbiB0YXhvbm9teS5xemEgXAogIC0taS1jbGFzc2lmaWVyICAvdWZyYy9zdHJhdXNzL2JsYWJsYSAgICAgICAgICAjSU5TRVJUIFBBVEggVE8gWU9VUiBQUkVUUkFJTkVEIERBVEFCQVNFIAoKcWlpbWUgbWV0YWRhdGEgdGFidWxhdGUgXAogIC0tbS1pbnB1dC1maWxlIHRheG9ub215LnF6YSBcCiAgLS1vLXZpc3VhbGl6YXRpb24gdGF4b25vbXkucXp2CgpxaWltZSB0YXhhIGJhcnBsb3QgXAogIC0taS10YWJsZSB0YWJsZS5xemEgXAogIC0taS10YXhvbm9teSB0YXhvbm9teS5xemEgXAogIC0tby12aXN1YWxpemF0aW9uIHRheGEtYmFyLXBsb3RzLnF6diBcCiAgLS1tLW1ldGFkYXRhLWZpbGUgLi4vYmxhYmxhICAgICAJCSAgICAgICAgICAjSU5TRVJUIFBBVEggVE8gVkFMSURBVEVEIE1BUFBJTkcgRklMRQoKCiMgVW5sb2FkIG1vZHVsZXM6Cm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCgpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy80X3RheG9ub215X1NJTFZBLnNoCQkKYGBgCiFbXShmaWd1cmVzL2xldmVsLTctYmFycy5zdmcpCgpPcHRpb25hbGx5LCB5b3UgY2FuIHRyYWluIHlvdXIgb3duIGNsYXNzaWZpZXIuIEZvciB0aGF0LCB5b3Ugd2lsbCBmaXJzdCBuZWVkIHRvIGRvd25sb2FkIGEgZmFzdGEgZGF0YWJhc2UgYW5kIHRoZSByZWxhdGVkIHRheG9ub215IGZpbGUgKGkuZS4gU0lMVkEgMTI4KS4gT25jZSB5b3UgZG93bmxvYWRlZCBpdCB5b3UgaGF2ZSB0byBrbm93OiAKLQl5b3VyIGZ3IHByaW1lciBzZXF1ZW5jZQotCXlvdXIgcmV2IHByaW1lciBzZXF1ZW5jZQotCXRoZSBtYXhpbXVtIGxlbmd0aCB0byB5b3VyIHJlYWRzIChzaW5nbGUsIG5vdCBtZXJnZWQpClRvZ2V0aGVyIHdpdGggdGhlIGZhc3RhIGFuZCB0YXhvbm9teSBmaWxlcywgdGhlc2UgYXJlIHRoZSBpbnB1dHMgb2YgdGhlIG9wdDFfdHJhaW5fc2Npa2l0LnNoIHNjcmlwdCwgd2hpY2ggd2lsbCBidWlsZCBhbm90aGVyIHRyYWluZWQgY2xhc3NpZmllciBmcm9tIHlvdXIgZGF0YWJhc2UsIHRydW5jYXRlZCBhdCB0aGUgcmVnaW9uIG9mIGludGVyZXN0ICh3aGljaCB3aWxsIHJlZHVjZSB0aGUgY29tcHV0YXRpb25hbCBwb3dlciBhbmQgdGltZSByZXF1aXJlZCBmb3IgdGhlIHRheG9ub215IHNjcmlwdCkuIAoKICAgIE5PVEU6IHRoZXJlIGlzIGEgU0lMVkEgcHJlLXRyYWluZWQgZGF0YWJhc2UgZm9yIHZlcnNpb24gMTMyIGF2YWlsYWJsZSBvbiB0aGUgcWlpbWUyIHdlYnNpdGUuIEkgdGhpbmsgaXQgY291bGQgYmUgdXNlZCBmb3Igb3VyIHByaW1lcnMsIGJ1dCBuZWVkIHRvIGRvdWJsZS1jaGVjay4KYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy9vcHRfdHJhaW5fc2tsZWFybi5zaApgYGAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLUEgc3RyYXVzcwojU0JBVENIIC1KIHNjaWtpdF90cmFpbmluZwojU0JBVENIIC1OIDEKI1NCQVRDSCAtLXRpbWU9MjQ6MDA6MDAKI1NCQVRDSCAtLW1lbT00MGcJCQkgICAgICAgICAgICAgICAgICAgICAgICAgICNUT1RBTCBSQU0gUEVSIFRBU0sKI1NCQVRDSCAtRCAvdWZyYy9zdHJhdXNzLyAJCSAgICAgICAgICAgICAgICAgICNQQVRIIFRPIEEgREFUQUJBU0UgRk9MREVSIE9GIFlPVVIgQ0hPSUNFCiNTQkFUQ0ggLW8gbG9ncy9xMl9zY2lraXRfdHJhaW5fJWoub3V0CSAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIC0tLS0tLS0tLS0tLS0tLS1Ib3VzZWtlZXBpbmctLS0tLS0tLS0tLS0tLS0tLS0tLQpybSAtciAJI05BTUUgT0YgVEhFIE5FVyBEQVRBQkFTRSBGT0xERVIgCm1rZGlyIAkjTkFNRSBPRiBUSEUgTkVXIERBVEFCQVNFIEZPTERFUgpjZCAJI05BTUUgT0YgVEhFIE5FVyBEQVRBQkFTRSBGT0xERVIKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnFpaW1lIHRvb2xzIGltcG9ydCBcCiAgLS10eXBlICdGZWF0dXJlRGF0YVtTZXF1ZW5jZV0nIFwKICAtLW91dHB1dC1wYXRoIGltcG9ydGVkLWZhc3RhLWRhdGFiYXNlLnF6YSBcCiAgLS1pbnB1dC1wYXRoIC91ZnJjL3N0cmF1c3MvYmxhYmxhICAgI0lOU0VSVCBQQVRIIFRPIFRIRSByZXBfc2V0L3JlcF9zZXRfYWxsLzk3Lzk3X290dXMuZmFzdGEgRklMRQoKCnFpaW1lIHRvb2xzIGltcG9ydCBcCiAgLS10eXBlICdGZWF0dXJlRGF0YVtUYXhvbm9teV0nIFwKICAtLXNvdXJjZS1mb3JtYXQgSGVhZGVybGVzc1RTVlRheG9ub215Rm9ybWF0IFwKICAtLW91dHB1dC1wYXRoIGltcG9ydGVkLXRheG9ub215LnF6YSBcCiAgLS1pbnB1dC1wYXRoIC91ZnJjL3N0cmF1c3MvYmxhYmxhICNJTlNFUlQgUEFUSCBUTyBUSEUgdGF4b25vbXlfYWxsLzk3L2NvbnNlbnN1c190YXhvbm9teV83X2xldmVscy50eHQgRklMRQoKcWlpbWUgZmVhdHVyZS1jbGFzc2lmaWVyIGV4dHJhY3QtcmVhZHMgXAogIC0taS1zZXF1ZW5jZXMgaW1wb3J0ZWQtZmFzdGEtZGF0YWJhc2UucXphICBcCiAgLS1wLWYtcHJpbWVyIAlcCSAgICAjSU5TRVJUIEZXIFBSSU1FUiBTRVFVRU5DRSBCRUZPUkUgVEhFIEZXIFNMQVNIIEFORCBERUxFVEUgVEhJUyBJTlNUUlVDVElPTgogIC0tcC1yLXByaW1lciAgXCAgIAkjSU5TRVJUIFJFViBQUklNRVIgU0VRVUVOQ0UgQkVGT1JFIFRIRSBGVyBTTEFTSCBBTkQgREVMRVRFIFRISVMgSU5TVFJVQ1RJT04KICAtLXAtdHJ1bmMtbGVuICBcICAJI0lOU0VSVCBMRU5HVEggT0YgVFJJTU1FRCBTRVFVRU5DRVMgQkVGT1JFIFRIRSBGVyBTTEFTSCBBTkQgREVMRVRFIFRISVMgCiAgLS1vLXJlYWRzIHRydW5jYXRlZC1pbXBvcnRlZC1kYi5xemEKCnFpaW1lIGZlYXR1cmUtY2xhc3NpZmllciBmaXQtY2xhc3NpZmllci1uYWl2ZS1iYXllcyBcCiAgLS1pLXJlZmVyZW5jZS1yZWFkcyB0cnVuY2F0ZWQtaW1wb3J0ZWQtZGIucXphIFwKICAtLWktcmVmZXJlbmNlLXRheG9ub215IGltcG9ydGVkLXRheG9ub215LnF6YSBcCiAgLS1vLWNsYXNzaWZpZXIgCS91ZnJjL3N0cmF1c3MvYmxhYmxhICAgICAgICAgICAgICAgICAgICAgICNJTlNFUlQgTkFNRSBPRiBZT1VSIEZJTkFMIENMQVNTSUZJRVIKCm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCgpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy9vcHRfdHJhaW5fc2tsZWFybi5zaApgYGAKIyM1X1BJQ1JVU1Quc2gKVG8gZG8gdGhlIG1ldGFib2xpYyBwcmVkaWN0aW9uIGluIFBJQ1JVU1QganVzdCB1c2UgdGhlIGZvbGxvd2luZyBzY3JpcHQuIEl0IHdpbGwgcmVhc3NpZ24gdGhlIHRheG9ub215IHRvIHRoZSBHcmVlbmdlZW5lcyBkYXRhYmFzZSAod2hpY2guLi4pIGluIHFpaW1lMSBzbyBiZSBzdXJlIHRvIGhhdmUgYSB0aGUgbmVjZXNzYXJ5IGZpbGVzIGFzIHdlbGwuIAoKICAgIE5PVEU6IEF0IHRoZSB0aW1lIG9mIHdyaXRpbmcsIFBJQ1JVU1QyIGlzIHN0aWxsIGluIGJldGEgKGh0dHBzOi8vZ2l0aHViLmNvbS9waWNydXN0L3BpY3J1c3QyKSBidXQgbWlnaHQgYmUgd29ydGgga2VlcGluZyBhbiBleWUgb24uClRoZSByZXN1bHRzIGFyZSBzdG9yZWQgYXMgcHJlZGljdGVkX21ldGFnZW5vbWVzLkwzLmJpb20gYW5kIG1ldGFnZW5vbWVfcHJlZGljdGlvbnMuYmlvbS4gSSBtYWtlIHNvbWUgcGxvdHMgdXNpbmcgaXRzIG93biBjb21tYW5kcywgYnV0IHlvdSdkIGJldHRlciBkbyB0aGVtIGFueXdoZXJlIGVsc2UuIAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy81X1BJQ1JVU1Quc2gKYGBgCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiMgLS0tLS0tLS0tLS0tLS0tLVNMVVJNIFBhcmFtZXRlcnMtLS0tLS0tLS0tLS0tLS0tCgojU0JBVENIIC1BIHN0cmF1c3MKI1NCQVRDSCAtSiBQaUNSVVN0CiNTQkFUQ0ggLU4gMQojU0JBVENIIC0tdGltZT03MjowMDowMAojU0JBVENIIC0tbWVtPTI1ZwkJCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjVE9UQUwgUkFNIFBFUiBUQVNLCQkKI1NCQVRDSCAtbiA4CQkJCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNOVU1CRVIgT0YgQ1BVUyBQRVIgVEFTSwojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvMTZTICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLW8gbG9ncy81X1BJQ1JVU3RfJWoub3V0CSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI1BBVEggT0YgTE9HIEZJTEUKCmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgUHJlZGljdCBmdW5jdGlvbmFsaXRpZXMgb2YgdGhlIGdlbm9tZSBmcm9tIHRheG9ub21pY2FsIGFzc2lnbm1lbnRzIHVzaW5nIEtlZ2dPCiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBxaWltZTIKCiMgLS0tLS0tLS0tLS0tLS0tLUhvdXNla2VlcGluZy0tLS0tLS0tLS0tLS0tLS0tLS0tCnJtIC1yIFBJQ1JVU3QKbWtkaXIgUElDUlVTdAoKIyAtLS0tLS0tLS0tLS0tLS0tQ29tbWFuZHMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KY3AgZmVhdHVyZXMvdGFibGUucXphIFBJQ1JVU3QvaW1wdGFiLnF6YQoKcWlpbWUgdG9vbHMgZXhwb3J0IFwKIC0taW5wdXQtcGF0aCBmZWF0dXJlcy9yZXAtc2Vxcy5xemEgXAogIC0tb3V0cHV0LXBhdGggUElDUlVTdAoKIyBTd2l0Y2ggbW9kdWxlczoKbW9kdWxlIHVubG9hZCBxaWltZTIKbW9kdWxlIGxvYWQgcWlpbWUvMS45LjEKCmNkIFBJQ1JVU3QKZWNobyAicGlja19vdHVzOmVuYWJsZV9yZXZfc3RyYW5kX21hdGNoIFRydWUiICA+PiAkUFdEL290dV9waWNraW5nX3BhcmFtc185Ny50eHQKZWNobyAicGlja19vdHVzOnNpbWlsYXJpdHkgMC45NyIgPj4gJFBXRC9vdHVfcGlja2luZ19wYXJhbXNfOTcudHh0CgpwaWNrX2Nsb3NlZF9yZWZlcmVuY2Vfb3R1cy5weSBcCiAtaSBkbmEtc2VxdWVuY2VzLmZhc3RhIFwKIC1vIGdnIFwKIC1hIC1PIDggXAogLXAgb3R1X3BpY2tpbmdfcGFyYW1zXzk3LnR4dCBcCiAtciAvdWZyYy9zdHJhdXNzL2JsYWJsYSBcICAgICAgICAjSU5TRVJUIFBBVEggVE8gVEhFIGdnXzEzXzhfb3R1cy9yZXBfc2V0Lzk3X290dXMuZmFzdGEgRklMRSBBTkQgREVMRVRFIFRISVMgSU5TVFJVQ1RJT04KIC10IC91ZnJjL3N0cmF1c3MvYmxhYmxhICAgICAgICAgICNJTlNFUlQgUEFUSCBUTyBUSEUgZ2dfMTNfOF9vdHVzL3RheG9ub215Lzk3X290dV90YXhvbm9teS50eHQgRklMRQoKZmlsdGVyX3RheGFfZnJvbV9vdHVfdGFibGUucHkgXAogIC1pIGdnLyouYmlvbSBcCiAgLW8gdGFibGVfd29fY2hsX21pdC5iaW9tIFwKICAtbiBjX19DaGxvcm9wbGFzdCxmX19NaXRvY2hvbmRyaWEKCm12IHRhYmxlX3dvX2NobF9taXQuYmlvbSBwaWNydXN0X2lucHV0LmJpb20KCmZpbHRlcl9vdHVzX2Zyb21fb3R1X3RhYmxlLnB5IFwKIC1pIHBpY3J1c3RfaW5wdXQuYmlvbSBcCiAtbyBjbG9zZWRfb3R1X3RhYmxlLmJpb20gXAogLS1uZWdhdGVfaWRzX3RvX2V4Y2x1ZGUgXAogLWUgL3VmcmMvc3RyYXVzcy9ibGFibGEgICAgICAgICNJTlNFUlQgUEFUSCBUTyBUSEUgZ2dfMTNfOF9vdHVzL3JlcF9zZXQvOTdfb3R1cy5mYXN0YSBGSUxFCgpmaWx0ZXJfc2FtcGxlc19mcm9tX290dV90YWJsZS5weSBcCiAtaSBwaWNydXN0X2lucHV0LmJpb20gXAogLW8gY2xvc2VkX290dV90YWJsZV9maWx0LmJpb20gXAogLW4gMQptb2R1bGUgcHVyZ2UKbW9kdWxlIGxvYWQgZ2NjLzUuMi4wCm1vZHVsZSBsb2FkIHBpY3J1c3QvMS4xLjMKCm5vcm1hbGl6ZV9ieV9jb3B5X251bWJlci5weSBcCiAtaSBjbG9zZWRfb3R1X3RhYmxlX2ZpbHQuYmlvbSBcCiAtbyBub3JtYWxpemVkX290dXMuYmlvbQoKcHJlZGljdF9tZXRhZ2Vub21lcy5weSAtaSBub3JtYWxpemVkX290dXMuYmlvbSAtbyBtZXRhZ2Vub21lX3ByZWRpY3Rpb25zLmJpb20gLWEgbnN0aV9wZXJfc2FtcGxlLnRhYgoKY2F0ZWdvcml6ZV9ieV9mdW5jdGlvbi5weSAtaSBtZXRhZ2Vub21lX3ByZWRpY3Rpb25zLmJpb20gLWMgS0VHR19QYXRod2F5cyAtbCAzIC1vIHByZWRpY3RlZF9tZXRhZ2Vub21lcy5MMy5iaW9tCgptZXRhZ2Vub21lX2NvbnRyaWJ1dGlvbnMucHkgLWkgbm9ybWFsaXplZF9vdHVzLmJpb20gLW8ga29fbWV0YWdlbm9tZV9jb250cmlidXRpb25zLnRhYiAtLWxvYWRfcHJlY2FsY19maWxlX2luX2Jpb20gLS1zdXBwcmVzc19zdWJzZXRfbG9hZGluZwoKY2F0ZWdvcml6ZV9ieV9mdW5jdGlvbi5weSAtaSBtZXRhZ2Vub21lX3ByZWRpY3Rpb25zLmJpb20gLWMgIktFR0dfUGF0aHdheXMiIC1sIDIgLW8gbWV0YWdlbm9tZV9hdF9sZXZlbDIuYmlvbQoKbW9kdWxlIHB1cmdlCm1vZHVsZSBsb2FkIHFpaW1lLzEuOS4xCgpiaW9tIGNvbnZlcnQgXAogLWkgcHJlZGljdGVkX21ldGFnZW5vbWVzLkwzLmJpb20gXAogLW8gcHJlZGljdGVkX21ldGFnZW5vbWVzLkwzLnRzdiBcCiAtLXRvLXRzdiBcCiAtLXRhYmxlLXR5cGUgIk9UVSB0YWJsZSIKCnNvcnRfb3R1X3RhYmxlLnB5IC1pIG1ldGFnZW5vbWVfcHJlZGljdGlvbnMuYmlvbSAgLW8gbWV0YWdlbm9tZV9wcmVkaWN0aW9ucy5ieV9jYXRlZ29yeS5iaW9tIC1zIFlPVVJfQ0FURUdPUlkgLW0gLi4vLi4vbWFwcGluZy50eHQgI0lOU0VSVCBZT1VSIE9XTiBDQVRFR09SWSBBTkQgUEFUSCBUTyBWQUxJREFURUQgTUFQUElORyBGSUxFCgplY2hvICJzdW1tYXJpemVfdGF4YTptZF9pZGVudGlmaWVyICAgIEtFR0dfUGF0aHdheXMiID4+ICRQV0QvcWlpbWVfcGFyYW1zLnR4dAplY2hvICJzdW1tYXJpemVfdGF4YTphYnNvbHV0ZV9hYnVuZGFuY2UgICBUcnVlIiA+PiAkUFdEL3FpaW1lX3BhcmFtcy50eHQKZWNobyAic3VtbWFyaXplX3RheGE6bGV2ZWwgICAgMiIgPj4gJFBXRC9xaWltZV9wYXJhbXMudHh0CgpzdW1tYXJpemVfdGF4YV90aHJvdWdoX3Bsb3RzLnB5IC1pIG1ldGFnZW5vbWVfYXRfbGV2ZWwyLmJpb20gLXAgcWlpbWVfcGFyYW1zLnR4dCAtbyBwbG90c19hdF9sZXZlbDIKCm1vZHVsZSB1bmxvYWQgcWlpbWUKCmRhdGUKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0Kc2JhdGNoIHNjcmlwdHMvNV9QSUNSVVNULnNoCmBgYAohW10oZmlndXJlcy9QaWNydXN0LnBuZykKCiNJVFMgcGlwZWxpbmUKVGhlIElUUyBwaXBlbGluZSBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIDE2UyBwaXBlbGluZSwgQlVUIGl0IGhhcyB0aGUgZm9sbG93aW5nIG1ham9yIGRpZmZlcmVuY2VzOgotIElUUzEgc2VxdWVuY2VzIGNvbnRhaW4gcGFydHMgb2YgdGhlIDhTIHVuaXQgYW5kIG9mIHRoZSBJVFMyIHNlcXVlbmNlcyB3aGljaCBtdXN0IGJlIHRyaW1tZWQuIAotIElUUyBzZXF1ZW5jZXMgYXJlIG5vdCBhbGwgdGhlIHNhbWUgbGVuZ3RoLCBjb250cmFyeSB0byAxNlMuIFRoZXJlZm9yZSwgREFEQTIgcmVxdWlyZSBkaWZmZXJlbnQgcGFyYW1ldGVycy4KLSBVTklURSBkYXRhYmFzZSBpcyB1c2VkIGZvciBJVFMgc2VxdWVuY2VzIGluc3RlYWQgb2YgU0lMVkEgZGF0YWJhc2UuIAoKICAgIE5PVEU6IHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uIG9mIHFpaW1lMiBpbmNsdWRlIGFuIElUUyBwaXBlbGluZSB0dXRvcmlhbCwgd2hpY2ggSSBoYXZlbid0IGxvb2tlZCBhdCB0aGUgbW9tZW50IG9mIHdyaXRpbmcuCiAgICAKIyMwX3NldHVwLnNoCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmNkIElUUwpta2RpciByYXdfc2Vxcwpta2RpciBsb2dzCm1rZGlyIHNjcmlwdHMKYGBgCgpOb3cgbW92ZSB5b3VyIGNvbXByZXNzZWQgc2VxdWVuY2UgZmlsZXMgaW4gdGhlIGByYXdfc2Vxc2AgZGlyZWN0b3J5IGZvbGxvd2luZyB0aGUgaW5zdHJ1Y3Rpb25zIGZydG9tIHRoZSBIaXBlcmdhdG9yIHdpa2kgcGFnZS4gVGhlbiBzdGFydCB3cml0aW5nIHRoZSBmaXJzdCBiYXNoIHNjcmlwdCwgdXNpbmcgCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpuYW5vIHNjcmlwdHMvMF9zZXR1cC5zaApgYGAgCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiNTQkFUQ0ggLS1hY2NvdW50PXN0cmF1c3MKI1NCQVRDSCAtLWpvYi1uYW1lPXNldHVwCiNTQkFUQ0ggLS1udGFza3M9MQojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvSVRTICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLW8gbG9ncy8wX3NldHVwXyVqLm91dApkYXRlO2hvc3RuYW1lO3B3ZAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIwojIFNldHVwIGRhdGEgZGlyZWN0b3J5IGFuZCBjb3B5IHJhd19zZXFzIGNvbnRlbnRzCiMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMjIyMjIFNldHVwICMjIyMjCiMgTG9hZCBtb2R1bGUocyk6CgojIEhvdXNla2VlcGluZzoKcm0gLXJmIGRhdGEKCiMgTWFrZSBuZWNlc3NhcnkgZGlyZWN0b3JpZXM6Cm1rZGlyIGRhdGEKbWtkaXIgZGF0YS9yYXdfZGF0YQoKIyMjIyMgUnVuIGNvbW1hbmRzICMjIyMjCiMgSWYgc2VxdWVuY2VzIGFyZSBpbmRpdmlkdWFsIGRpcmVjdG9yaWVzIChpZiBub3QsIGNvbW1lbnQgdGhpcyBvdXQpOgpmb3IgZGlyIGluIHJhd19zZXFzLyo7IGRvCiAgICBjcCAkZGlyLyogZGF0YS9yYXdfZGF0YS8uCmRvbmUgCgpjZCBkYXRhL3Jhd19kYXRhCmd1bnppcCAqLmd6CgojIEZpeCBuYW1lczogdGhpcyBkZXBlbmRzIG9mIGNvdXJzZSBvbiBob3cgeW91ciBmaWxlcyBhcmUgbmFtZWQuIENIRUNLIFRIRU0hCmZvciBmaWxlIGluIGRhdGEvcmF3X2RhdGEvKi5nejsgZG8KICAgIG12ICRmaWxlICR7ZmlsZS9TYXJhaD8tL307CiAgICBtdiAkZmlsZSAke2ZpbGUvU2FyYWg/Py0vfTsKICAgIG12ICRmaWxlICR7ZmlsZS9TYXJhaD8/Py0vfTsKZG9uZQoKIyBNb3ZlIGZpbGVzIGludG8gdGhlaXIgcmVzcGVjdGl2ZSBkaXJlY3Rvcnk6Cm1rZGlyIFIxcwpta2RpciBSMnMKbXYgKl9SMV8qIFIxcy8uCm12ICpfUjJfKiBSMnMvLgoKIyBDb25jYXRlbmF0ZSBpbnRvIGEgc2luZ2xlIGZpbGUKY2F0IFIxcy8qID4+IFIxLmZxCmNhdCBSMnMvKiA+PiBSMi5mcQoKZGF0ZQpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8wX3NldHVwLnNoCmBgYAoKIyMxX21lcmdlX2FuZF90cmltLnNoClRoaXMgaXMgdGhlIGZpcnN0IGRpZmZlcmVuY2U6IGluc3RlYWQgb2YgdXNpbmcgZGlyZWN0bHkgREFEQTIgdG8gbWVyZ2UgdGhlIHBpcmVkIGVuZHMsIHdlIHdpbGwgdXNlIGBQRUFSYCAoaHR0cHM6Ly9zY28uaC1pdHMub3JnL2V4ZWxpeGlzL3dlYi9zb2Z0d2FyZS9wZWFyLykgd2hpY2ggd2lsbCByZXRhaW4gdGhlIHF1YWxpdHkgb2YgdGhlIGJhc2UgY2FsbHMuIFRoZW4gd2Ugd2lsbCB0cmltIHRoZSBzZXF1ZW5jZXMgcmVtb3ZpbmcgdGhlIHVud2FudGVkIHJlZ2lvbnMgdXNpbmcgYGN1dGFkYXB0YCAoaHR0cDovL2pvdXJuYWwuZW1ibmV0Lm9yZy9pbmRleC5waHAvZW1ibmV0am91cm5hbC9hcnRpY2xlL3ZpZXcvMjAwLCBub3cgYXZhaWxhYmxlIGFsc28gaW4gUWlpbWUyLCBidXQgaGVyZSB1c2VkIGFzIGlzKS4KCipJTVBPUlRBTlQqOiBUaGUgc2NyaXB0IHdpbGwgZXh0cmFjdCB0aGUgYmFyY29kZXMgZnJvbSB0aGUgc2VxdWVuY2VzIHVzaW5nIHFpaW1lMS4gSXQgd2lsbCB0aGVuIHByb2R1Y2UgYSBgdHh0YCBmaWxlIHdoaWNoIGNvbnRhaW5zIHRoZSBiYXJjb2RlcyBhc3NvY2lhdGVkIHRvIGV2ZXJ5IGZpbGUuIFlvdSBuZWVkIHRvIHdyaXRlIHRob3NlIGJhcmNvZGVzIGluIHlvdXIgbWFwcGluZyBmaWxlLCBpbiB0aGUgY29sdW1uIGBCYXJjb2RlU2VxdWVuY2VgIG90aGVyd2lzZSB5b3Ugd2lsbCBub3QgYmUgYWJsZSB0byBpbXBvcnQgdGhlIHNlcXVlbmNlLiBQYXkgYXR0ZW50aW9uIHRvIHRoZSBjb3JyZWN0IGFzc29jaWF0aW9ucyBiZXR3ZWVuIGJhcmNvZGVzIGFuZCBmaWxlIG5hbWVzIHdoZW4gYnVpbGRpbmcgeW91ciBtYXBwaW5nIGZpbGVzISEhIAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy8xX21lcmdlX2FuZF90cmltLnNoCmBgYApgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiMgLS0tLS0tLS0tLS0tLS0tLVNMVVJNIFBhcmFtZXRlcnMtLS0tLS0tLS0tLS0tLS0tCgojU0JBVENIIC0tYWNjb3VudD1zdHJhdXNzCiNTQkFUQ0ggLS1qb2ItbmFtZT1tZXJnZV90cmltCiNTQkFUQ0ggLS10aW1lPTg6MDA6MDAKI1NCQVRDSCAtLW50YXNrcz0xCiNTQkFUQ0ggLW4gOAojU0JBVENIIC0tbWVtPTIwZwojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvSVRTICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLW8gbG9ncy8xX3BlYXJfY3V0YWRhcHRfJWoub3V0CmRhdGU7aG9zdG5hbWU7cHdkCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojCiMgTWVyZ2UgSVRTIHBhaXJlZCBlbmRzIGFuZCB0cmltcyBhd2F5IHJlZ2lvbnMgb3V0c2lkZSBwcmltZXJzCiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBwZWFyCgojIC0tLS0tLS0tLS0tLS0tLS1Ib3VzZWtlZXBpbmctLS0tLS0tLS0tLS0tLS0tLS0tLS0Kcm0gLXIgZmVhdHVyZXMKbWtkaXIgZmVhdHVyZXMKY2QgZGF0YQpybSAtciBtZXJnZS5wZWFyLioKcm0gbm8qLmZhc3RxCnJtIHRyaW1tZWQtc2Vxcy5mYXN0cQoKCiMgLS0tLS0tLS0tLS0tLS0tLUNvbW1hbmRzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIE1lcmdlIHBhaXJlZCBlbmQgcmVhZHMKcGVhciAtaiA4IC15IDE1R1wKICAtZiByYXdfZGF0YS9SMS5mcSBcCiAgLXIgcmF3X2RhdGEvUjIuZnEgXAogIC1vIG1lcmdlLnBlYXIKCm1vZHVsZSB1bmxvYWQgcGVhcgptb2R1bGUgbG9hZCBjdXRhZGFwdAoKI1RyaW0gb3V0IHByaW1lcnMgCmN1dGFkYXB0IC1hIEdDQVRDR0FUR0FBR0FBQ0dDQUdDIC1vIG5vZncuZmFzdHEgbWVyZ2UucGVhci5hc3NlbWJsZWQuZmFzdHEgCmN1dGFkYXB0IC1nIENUVEdHVENBVFRUQUdBR0dBQUdUQUEgLW8gbm9wcmltZXItc2Vxcy5mYXN0cSBub2Z3LmZhc3RxCgojVHJpbSBvdXQgNS44UyBhbmQgU1NVCmN1dGFkYXB0IC1nIENUVEdHVENBVFRUQUdBR0dBQUdUQUFBQUdUQ0dUQUFDQUFHR1RUVENDR1RBR0dUR0FBQ0NUR0NHR0FBR0dBVENBVFQgLWEgQUFDVFRUQ0FBQ0FBQ0dHQVRDVENUVEdHWVRDVFNHQ0FUQ0dBVEdBQUdBQUNHQ0FHQyAtbyB0cmltbWVkLXNlcXMuZmFzdHEgbm9wcmltZXItc2Vxcy5mYXN0cQoKbW9kdWxlIHVubG9hZCBjdXRhZGFwdCAKCm12IHRyaW1tZWQtc2Vxcy5mYXN0cSAuLi9mZWF0dXJlcy90cmltbWVkLXNlcXMuZmFzdHEKY2QgLi4vZmVhdHVyZXMKCiNFeHRyYWN0IGJhcmNvZGVzLCBuZWNlc3NhcnkgdG8gaW1wb3J0IGludG8gUWlpbWUyCm1vZHVsZSBsb2FkIHFpaW1lCgpleHRyYWN0X2JhcmNvZGVzLnB5IFwKIC1mIHRyaW1tZWQtc2Vxcy5mYXN0cSBcCiAtYyBiYXJjb2RlX2luX2xhYmVsIFwKIC0tY2hhcl9kZWxpbmVhdG9yICc6JyBcCiAtLWJjMV9sZW4gIDEwIFwKIC1vIC4KCm1vZHVsZSB1bmxvYWQgcWlpbWUKCmd6aXAgKgptdiB0cmltbWVkLXNlcXMuZmFzdHEuZ3ogc2VxdWVuY2VzLmZhc3RxLmd6CgojSW4gY2FzZSB5b3UgbmVlZCB0byByZWJ1aWxkIHlvdXIgbWFwcGluZyBmaWxlLCB5b3UgY2FuIGV4dHJhY3QgZmlsZW5hbWVzIGFuZCBmaXJzdAojbGluZXMgZnJvbSB5b3VyIG9yaWdpbmFsIHNlcXVlbmNlcyB3aXRoIApjZCAuLi9kYXRhL3Jhd19kYXRhL1IxcwpoZWFkIC1uMSAqLmZhc3RxID4gLi4vc2VxdWVuY2VzX3dpdGhfaGVhZGVycy50eHQKCiNZb3Ugd2lsbCBoYXZlIHRoZW4gYSBmaWxlIGluIHdoaWNoIGZvciBlYWNoIHBhaXIgb2YgbGluZXMsIHRoZSBmaXJzdCBvbmUgaXMgdGhlCiNmaWxlbmFtZSBhbmQgdGhlIHNlY29uZCBvbmUgaXMgdGhlIGhlYWRlciwgb2Ygd2ljaCB0aGUgbGFzdCBjaGFyYWN0ZXJzIGFmdGVyIHRoZSAnOicKI2FyZSB0aGUgYXNzb2NpYXRlZCBiYXJjb2RlLiBZb3UgY2FuIGVkaXQgdGhpcyBmaWxlIGVsc2V3aGVyZSBhbmQgdXNlIGl0IHRvIGdldCB0aGUKI2JhcmNvZGVzIGFzc29jaWF0ZWQgZm9yIGVhY2ggc2FtcGxlIGFuZCB0aGVuIHBhc3RlIHRoZW0gaW4gdGhlIEJhcmNvZGVTZXF1ZW5jZXMgZmllbGQKI29mIHRoZSBtYXBwaW5nIGZpbGUuIFBheSBhdHRlbnRpb24gdG8gdGhlIGNvcnJlY3Qgb3JkZXIgb2YgZmlsZSBuYW1lcyEhCgpkYXRlCmBgYApFeGl0IHVzaW5nIGBjdHJsICsgWGAgYW5kIHNhdmUgd2l0aCBgWWAuIFRoZW4gZG8KYGBge2Jhc2gsIGV2YWw9RkFMU0V9CnNiYXRjaCBzY3JpcHRzLzFfbWVyZ2VfYW5kX3RyaW0uc2gKYGBgCgojIzJfaW1wb3J0LnNoCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzJfaW1wb3J0LnNoCmBgYAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CiMhL2Jpbi9iYXNoCgojIC0tLS0tLS0tLS0tLS0tLS1TTFVSTSBQYXJhbWV0ZXJzLS0tLS0tLS0tLS0tLS0tLQoKI1NCQVRDSCAtLWFjY291bnQ9c3RyYXVzcwojU0JBVENIIC0tam9iLW5hbWU9aW1wb3J0X0lUUwojU0JBVENIIC0tdGltZT04OjAwOjAwCiNTQkFUQ0ggLS1udGFza3M9MQojU0JBVENIIC1uIDgKI1NCQVRDSCAtLW1lbT0yMGcKI1NCQVRDSCAtRCAvdWZyYy9zdHJhdXNzL3lvdXJfYWNjb3VudC95b3VyX3dvcmtpbmdfZGlyZWN0b3J5L0lUUyAgI1BBVEggT0YgWU9VUiBXT1JLSU5HIEZPTERFUgojU0JBVENIIC1vIGxvZ3MvMl9pbXBvcnRfcTJfJWoub3V0CiNTQkFUQ0ggLUEgc3RyYXVzcwpkYXRlO2hvc3RuYW1lO3B3ZAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIwojIEltcG9ydHMgcmVhZHMgaW50byBRaWltZTIgYXJ0aWZhY3RzIGFuZCBidWlsZHMgdmlzdWFsaXphdGlvbnMgCiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBxaWltZTIKCiMgLS0tLS0tLS0tLS0tLS0tLUhvdXNla2VlcGluZy0tLS0tLS0tLS0tLS0tLS0tLS0tCmNkIGZlYXR1cmVzCnJtIC1yICoucXphCgojIC0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKI0ltcG9ydCBEYXRhIGluIHFpaW1lMiBhcnRpZmFjdApxaWltZSB0b29scyBpbXBvcnQgXAogIC0tdHlwZSBFTVBTaW5nbGVFbmRTZXF1ZW5jZXMgXAogIC0taW5wdXQtcGF0aCAuIFwKICAtLW91dHB1dC1wYXRoIHRyaW1tZWQtc2Vxcy5xemEKCnFpaW1lIGRlbXV4IGVtcC1zaW5nbGUgXAogLS1pLXNlcXMgdHJpbW1lZC1zZXFzLnF6YSBcCiAtLW0tYmFyY29kZXMtY29sdW1uIEJhcmNvZGVTZXF1ZW5jZSBcCiAtLW8tcGVyLXNhbXBsZS1zZXF1ZW5jZXMgZGVtdWx0aXBsZXhlZC1zZXFzLnF6YSBcCiAtLW0tYmFyY29kZXMtZmlsZSAuLi4vYmxhYmxhICAgICAJCSAgICAgICAgICAjSU5TRVJUIFBBVEggVE8gVkFMSURBVEVEIE1BUFBJTkcgRklMRQoKIyBWaXN1YWxpemF0aW9ucwpxaWltZSBkZW11eCBzdW1tYXJpemUgXAogIC0taS1kYXRhIGRlbXVsdGlwbGV4ZWQtc2Vxcy5xemEgXAogIC0tby12aXN1YWxpemF0aW9uIGRlbXVsdGlwbGV4ZWQtc2Vxcy5xenYKCm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCgpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8xX21lcmdlX2FuZF90cmltLnNoCmBgYAoKIyMzX2RhZGEyX3NpbmdsZS5zaApTZWNvbmQgZGlmZmVyZW5jZTogREFEQTIgd2l0aCBkaWZmZXJlbnQgcGFyYW1ldGVycwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzNfZGFkYTJfc2luZ2xlLnNoCmBgYAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CiMhL2Jpbi9iYXNoCgojIC0tLS0tLS0tLS0tLS0tLS1TTFVSTSBQYXJhbWV0ZXJzLS0tLS0tLS0tLS0tLS0tLQoKI1NCQVRDSCAtLXRpbWU9MjQ6MDA6MDAKI1NCQVRDSCAtTiAxCiNTQkFUQ0ggLUogZGVub2lzZV9zaW5nbGUKI1NCQVRDSCAtbiAxNCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI05VTUJFUiBPRiBDUFVTIFBFUiBUQVNLCiNTQkFUQ0ggLS1tZW09NDBnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNNRU1PUlkgUEVSIFRBU0sKI1NCQVRDSCAtRCAvdWZyYy9zdHJhdXNzL3lvdXJfYWNjb3VudC95b3VyX3dvcmtpbmdfZGlyZWN0b3J5L0lUUyAgI1BBVEggT0YgWU9VUiBXT1JLSU5HIEZPTERFUgojU0JBVENIIC1vIGxvZ3MvM19kZW5vaXNlX3NpbmdsZXNfcTJfJWoub3V0CiNTQkFUQ0ggLUEgc3RyYXVzcwoKZGF0ZTtob3N0bmFtZTtwd2QKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMKIyBCdWlsZCBmZWF0dXJlIHRhYmxlIHJlcXVpcmVkIGZvciBmdXJ0aGVyIGFuYWx5c2lzCiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBxaWltZTIKCiMgSG91c2VrZWVwaW5nOgpjZCBmZWF0dXJlcwoKIyAtLS0tLS0tLS0tLS0tLS0tQ29tbWFuZHMtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIApxaWltZSBkYWRhMiBkZW5vaXNlLXNpbmdsZSBcCiAgLS1pLWRlbXVsdGlwbGV4ZWQtc2VxcyBkZW11bHRpcGxleGVkLXNlcXMucXphIFwKICAtLXAtdHJpbS1sZWZ0IDEgXAogIC0tcC10cnVuYy1sZW4gMCBcCiAgLS1vLXJlcHJlc2VudGF0aXZlLXNlcXVlbmNlcyByZXAtc2Vxcy5xemEgXAogIC0tcC1uLXRocmVhZHMgMCBcCiAgLS1vLXRhYmxlIHRhYmxlLnF6YSBcCiAgLS1vLWRlbm9pc2luZy1zdGF0cyBzdGF0cy5xemEgXAogIC0tdmVyYm9zZQoKcWlpbWUgZmVhdHVyZS10YWJsZSBzdW1tYXJpemUgXAogIC0taS10YWJsZSB0YWJsZS5xemEgXAogIC0tby12aXN1YWxpemF0aW9uIHRhYmxlLnF6diBcCiAgLS1tLXNhbXBsZS1tZXRhZGF0YS1maWxlICAuLi9ibGFibGEgICAgIAkJICAgICAgICAgICNJTlNFUlQgUEFUSCBUTyBWQUxJREFURUQgTUFQUElORyBGSUxFCgpxaWltZSBmZWF0dXJlLXRhYmxlIHRhYnVsYXRlLXNlcXMgXAogIC0taS1kYXRhIHJlcC1zZXFzLnF6YSBcCiAgLS1vLXZpc3VhbGl6YXRpb24gcmVwLXNlcXMucXp2CgojIFVubG9hZCBtb2R1bGVzOgptb2R1bGUgdW5sb2FkIHFpaW1lMgoKZGF0ZQpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8zX2RhZGEyX3NpbmdsZS5zaApgYGAKCiMjNF9UYXhvbm9teV9VTklURS5zaApGaW5hbGx5IHRoZSBwaHlsb2dlbmV0aWMgYWZmaWxpYXRpb24gdXNpbmcgVU5JVEUgZGF0YWJhc2UuIFNpbWlsYXJseSB0byB3aGF0IGRvbmUgYmVmb3JlLCB3ZSB3aWxsIHVzZSBhIHByZXRyYWluZWQgTmFpdmUgQmF5ZXMgY2xhc3NpZmllci4gVGhlcmVmb3JlLCBpZiB5b3Ugd2FudCB0byBjbGFzc2lmeSBhZ2FpbnN0IGEgZGlmZmVyZW50IHZlcnNpb24sIHlvdSB3aWxsIHVzZSB0aGUgb3B0aW9uYWwgdHJhaW5pbmcgc2NyaXB0IHByb3ZpZGVkLiAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpuYW5vIHNjcmlwdHMvNF9UYXhvbm9teV9VTklURS5zaApgYGAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLS1tZW09NTBnCiNTQkFUQ0ggLS10aW1lPTcyOjAwOjAwCiNTQkFUQ0ggLU4gMQojU0JBVENIIC1uIDEyCiNTQkFUQ0ggLUogdGF4b25vbXlfVU5JVEUKI1NCQVRDSCAtbyBsb2dzLzRfdGF4b25vbXlfVU5JVEVfJWoub3V0CiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS9JVFMgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtQSBzdHJhdXNzCgpkYXRlO2hvc3RuYW1lO3B3ZAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIwojIEFzc2lnbiB0YXhvbm9teSB1c2luZyBhIHByZS10cmFpbmVkIHNjaWtpdCBjbGFzc2lmaWVyIHZlcnNpb24gMC4xOS4xIGFuZCBVTklURSB2LjEyLTIwMTcKIyAKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS0tSG91c2VrZWVwaW5nLS0tLS0tLS0tLS0tLS0tLS0tLS0KY2QgZmVhdHVyZXMKcm0gdGF4b25vbXkucXphCnJtIHRheGEtYmFyLXBsb3RzLnRzdgpybSB0YXhvbm9teS5xenYKCiMgLS0tLS0tLS0tLS0tLS0tLUNvbW1hbmRzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpxaWltZSBmZWF0dXJlLWNsYXNzaWZpZXIgY2xhc3NpZnktc2tsZWFybiBcCiAgLS1pLXJlYWRzIHJlcC1zZXFzLnF6YSBcCiAgLS1vLWNsYXNzaWZpY2F0aW9uIHRheG9ub215LnF6YSBcCiAgLS1pLWNsYXNzaWZpZXIgIC91ZnJjL3N0cmF1c3MvYmxhYmxhICAgICAgICAgICNJTlNFUlQgUEFUSCBUTyBZT1VSIFBSRVRSQUlORUQgREFUQUJBU0UgCgpxaWltZSBtZXRhZGF0YSB0YWJ1bGF0ZSBcCiAgLS1tLWlucHV0LWZpbGUgdGF4b25vbXkucXphIFwKICAtLW8tdmlzdWFsaXphdGlvbiB0YXhvbm9teS5xenYKCnFpaW1lIHRheGEgYmFycGxvdCBcCiAgLS1pLXRhYmxlIHRhYmxlLnF6YSBcCiAgLS1pLXRheG9ub215IHRheG9ub215LnF6YSBcCiAgLS1vLXZpc3VhbGl6YXRpb24gdGF4YS1iYXItcGxvdHMucXp2IFwKICAtLW0tbWV0YWRhdGEtZmlsZSAuLi9ibGFibGEgICAgIAkJICAgICAgICAgICNJTlNFUlQgUEFUSCBUTyBWQUxJREFURUQgTUFQUElORyBGSUxFCgojIFVubG9hZCBtb2R1bGVzOgptb2R1bGUgdW5sb2FkIHFpaW1lMgoKZGF0ZQoKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0Kc2JhdGNoIHNjcmlwdHMvNF9UYXhvbm9teV9VTklURS5zaApgYGAKQW5kIGhlcmUncyB0aGUgb3B0Z2lvbmFsIHRyYWluaW5nCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpuYW5vIHNjcmlwdHMvb3B0X3RyYWluX3NrbGVhcm5fVU5JVEUuc2gKYGBgCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiMgLS0tLS0tLS0tLS0tLS0tLVNMVVJNIFBhcmFtZXRlcnMtLS0tLS0tLS0tLS0tLS0tCgojU0JBVENIIC0tbWVtPTMwZwojU0JBVENIIC0tdGltZT0yNDowMDowMAojU0JBVENIIC1OIDEKI1NCQVRDSCAtSiBzY2lraXRfdHJhaW5pbmcKI1NCQVRDSCAtRCAvdWZyYy9zdHJhdXNzLyAJCSAgICAgICAgICAgICAgICAgICNQQVRIIFRPIEEgREFUQUJBU0UgRk9MREVSIE9GIFlPVVIgQ0hPSUNFCiNTQkFUQ0ggLW8gbG9ncy9xMl9zY2lraXRfdHJhaW5fJWoub3V0CiNTQkFUQ0ggLUEgc3RyYXVzcwpkYXRlO2hvc3RuYW1lO3B3ZAoKIyAtLS0tLS0tLS0tLS0tLS0tSG91c2VrZWVwaW5nLS0tLS0tLS0tLS0tLS0tLS0tLS0KI3JtIFNJTFZBXzEyOF85OV9vdHVzLnF6YQojcm0gU0lMVkFfMTI4Xzk5X3RheC5xemEKI3JtIFNJTFZBXzEyOF85OV9vdHVzXzUxNS05MjYucXphCiNybSBTSUxWQV9uYl85OV9WMy1WNC5xemEKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMi8yMDE3LjExCgojIC0tLS0tLS0tLS0tLS0tLUNvbW1hbmRzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcWlpbWUgdG9vbHMgaW1wb3J0IFwKICAtLXR5cGUgRmVhdHVyZURhdGFbU2VxdWVuY2VdIFwKICAtLW91dHB1dC1wYXRoIFVOSVRFXzk5XzIwMTcuMTJfc2Vxcy5xemEgXAogIC0taW5wdXQtcGF0aCAgL3VmcmMvc3RyYXVzcy9ibGFibGEgICNJTlNFUlQgUEFUSCBUTyBzaF9yZWZzX3FpaW1lX3ZlcjdfOTlfc18wMS4xMi4yMDE3LmZhc3RhIAoKcWlpbWUgdG9vbHMgaW1wb3J0IFwKICAtLXR5cGUgRmVhdHVyZURhdGFbVGF4b25vbXldIFwKICAtLXNvdXJjZS1mb3JtYXQgSGVhZGVybGVzc1RTVlRheG9ub215Rm9ybWF0IFwKICAtLW91dHB1dC1wYXRoIFVOSVRFXzk5XzIwMTcuMTJfdGF4LnF6YSBcCiAgLS1pbnB1dC1wYXRoICAvdWZyYy9zdHJhdXNzL2JsYWJsYSAgI0lOU0VSVCBQQVRIIFRPIHNoX3RheG9ub215X3FpaW1lX3ZlcjdfOTlfc18wMS4xMi4yMDE3LnR4dCAKCgpxaWltZSBmZWF0dXJlLWNsYXNzaWZpZXIgZml0LWNsYXNzaWZpZXItbmFpdmUtYmF5ZXMgXAogIC0taS1yZWZlcmVuY2UtcmVhZHMgVU5JVEVfOTlfMjAxNy4xMl9zZXFzLnF6YSBcCiAgLS1pLXJlZmVyZW5jZS10YXhvbm9teSBVTklURV85OV8yMDE3LjEyX3RheC5xemEgXAogIC0tby1jbGFzc2lmaWVyIFVOSVRFXzk5XzIwMTcuMTJfY2xhc3NpZmllci5xemEKCm1vZHVsZSB1bmxvYWQgcWlpbWUyCgpkYXRlCgpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy9vcHRfdHJhaW5fc2tsZWFybl9VTklURS5zaApgYGAKCiMjNV9GVU5HVUlMRC5zaApNZXRhYm9saWMgcHJlZGljdGlvbnMgYXJlIGRvbmUgYnkgYXNzaWduaW5nIHRheGEgdG8gZ3VpbGRzLiAoaHR0cHM6Ly9naXRodWIuY29tL1VNTkZ1Ti9GVU5HdWlsZCkuIApUaGUgcmVzdWx0cyBhcmUgc3RvcmVkIGluIHR3byBmaWxlczogYSBmaWxlIGVuZGluZyB3aXRoIGd1aWxkcy50eHQgYW5kIGEgZ3VpbGRzX3VubWF0Y2hlZC50eHQuIFRoZXJlIGFyZSBubyB2aXN1YWxpemF0aW9ucyBmb3IgdGhhdCBzbyB0aGV5IG5lZWQgdG8gYmUgaW1wb3J0ZWQgYW5kIHZpc3VhbGl6ZWQgZWxzZXdoZXJlIChpLmUuIFNUQU1QLCBUYWJsZWF1LCBSLCBFeGNlbCkKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy81X0ZVTkdVSUxELnNoCmBgYAoKYGBge2Jhc2gsIGV2YWw9RkFMU0V9CiMhL2Jpbi9iYXNoCgojIC0tLS0tLS0tLS0tLS0tLS1TTFVSTSBQYXJhbWV0ZXJzLS0tLS0tLS0tLS0tLS0tLQoKIyNTQkFUQ0ggLUEgc3RyYXVzcwojU0JBVENIIC1KIEZ1bkd1aWxkCiNTQkFUQ0ggLU4gMQojU0JBVENIIC0tdGltZT03MjowMDowMAojU0JBVENIIC0tbWVtPTI1ZwkJCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjVE9UQUwgUkFNIFBFUiBUQVNLCQkKI1NCQVRDSCAtbiA4CQkJCQkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNOVU1CRVIgT0YgQ1BVUyBQRVIgVEFTSwojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvSVRTICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLW8gbG9ncy81X0Z1bmd1aWxkXyVqLm91dAkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICNQQVRIIE9GIExPRyBGSUxFCgpkYXRlO2hvc3RuYW1lO3B3ZAoKIyAtLS0tLS0tLS0tLS0tLS0tSG91c2VrZWVwaW5nLS0tLS0tLS0tLS0tLS0tLS0tLS0Kcm0gLXIgRnVuZ3VpbGQKbWtkaXIgRnVuZ3VpbGQKY2QgRnVuZ3VpbGQKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KcWlpbWUgdG9vbHMgZXhwb3J0IFwKICAtLWlucHV0LXBhdGggLi4vZmVhdHVyZXMvdGFibGUucXphIFwKICAtLW91dHB1dC1wYXRoIGV4cG9ydGVkLXRhYmxlCgpxaWltZSB0b29scyBleHBvcnQgXAogIC0taW5wdXQtcGF0aCAuLi9mZWF0dXJlcy90YXhvbm9teS5xemEgXAogIC0tb3V0cHV0LXBhdGggZXhwb3J0ZWQtdGF4b25vbXkKCm1vZHVsZSB1bmxvYWQgcWlpbWUyCm1vZHVsZSBsb2FkIHFpaW1lLzEuOS4xCgpiaW9tIGNvbnZlcnQgXAogIC1pIGV4cG9ydGVkLXRhYmxlL2ZlYXR1cmUtdGFibGUuYmlvbSBcCiAgLW8gZmVhdHVyZS1qc29uLmJpb20gXAogIC0tdGFibGUtdHlwZT0iT1RVIHRhYmxlIiBcCiAgLS10by1qc29uCgpzZWQgLWkgcy9UYXhvbi90YXhvbm9teS8gZXhwb3J0ZWQtdGF4b25vbXkvdGF4b25vbXkudHN2IHwgc2VkIC1pIHMvRmVhdHVyZVwgSUQvRmVhdHVyZUlELyBleHBvcnRlZC10YXhvbm9tJAoKYmlvbSBhZGQtbWV0YWRhdGEgXAogIC1pIGZlYXR1cmUtanNvbi5iaW9tIFwKICAtbyBmZWF0dXJlX3dfdGF4LmJpb20gXAogIC0tb2JzZXJ2YXRpb24tbWV0YWRhdGEtZnAgZXhwb3J0ZWQtdGF4b25vbXkvdGF4b25vbXkudHN2IFwKICAtLW9ic2VydmF0aW9uLWhlYWRlciBGZWF0dXJlSUQsdGF4b25vbXkgXAogIC0tc2Mtc2VwYXJhdGVkIHRheG9ub215CgpmaWx0ZXJfc2FtcGxlc19mcm9tX290dV90YWJsZS5weSBcCiAgLWkgZmVhdHVyZV93X3RheC5iaW9tIFwKICAtbyBmaWx0ZXJlZC10YWJsZS5iaW9tIFwKICAtbiAxCgpmaWx0ZXJfdGF4YV9mcm9tX290dV90YWJsZS5weSBcCiAgLWkgZmlsdGVyZWQtdGFibGUuYmlvbSBcCiAgLW8gdGFibGVfd29fY2hsX21pdC5iaW9tIFwKICAtbiBEXzJfX0NobG9yb3BsYXN0LERfNF9fTWl0b2Nob25kcmlhCiAgCmJpb20gY29udmVydCBcCiAgLWkgdGFibGVfd29fY2hsX21pdC5iaW9tIFwKICAtbyBmdW5naV90YWJsZS50eHQgXAogIC0tdG8tdHN2IFwKICAtLWhlYWRlci1rZXkgdGF4b25vbXkKICAKc2VkIC1pIHMvIiNPVFUgSUQiLyJPVFUgSUQiLyBmdW5naV90YWJsZS50eHQKc2VkIC1pICcxZCcgZnVuZ2lfdGFibGUudHh0IAoKd2dldCAtTyBGdW5ndWlsZC5weSBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vVU1ORnVOL0ZVTkd1aWxkL21hc3Rlci9HdWlsZHNfdjEuMS5weQoKcHl0aG9uMyBGdW5ndWlsZC5weSAtb3R1IGZ1bmdpX3RhYmxlLnR4dCAtZGIgZnVuZ2kgLW0gLXUKCm1vZHVsZSB1bmxvYWQgcWlpbWUKCmRhdGUKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0Kc2JhdGNoIHNjcmlwdHMvNV9GVU5HVUlMRC5zaApgYGAKCiNNZXJnZWQga2luZ2RvbXMKTm93IGl0J3MgdGltZSB0byBtZXJnZSB0aGUgdGF4b25vbXkgdGFibGVzIGFuZCB0aGUgZmVhdHVyZSB0YWJsZXMgb2YgMTZTIGFuZCBJVFMgaW50byBvbmUgc2luZ2xlIHRhYmxlLiBUaGVuLCBhbHNvIHRoZSByZXByZXNlbnRhdGl2ZSBzZXF1ZW5jZXMgb2J0YWluZWQgYnkgdGhlIERBREEyIG91dHB1dCB3aWxsIGJlIG1lcmdlZC4gQmUgY2FyZWZ1bCB3aXRoIHRoZSBtYXBwaW5nIGZpbGVzLCBiZSBzdXJlIHRoYXQgdGhleSBhbGwgaGF2ZSB0aGUgc2FtZSBudW1iZXIgYW5kIG9yZGVyIG9mIHNhbXBsZXMhCmBgYHtiYXNoIGV2YWw9RkFMU0V9CmNkIG1lcmdlZApta2RpciByYXdfc2Vxcwpta2RpciBsb2dzCm1rZGlyIHNjcmlwdHMKYGBgCiMjMV9tZXJnZV9raW5nZG9tcy5zaApgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzFfbWVyZ2Vfa2luZ2RvbXMuc2gKYGBgCgpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KIyEvYmluL2Jhc2gKCiMgLS0tLS0tLS0tLS0tLS0tLVNMVVJNIFBhcmFtZXRlcnMtLS0tLS0tLS0tLS0tLS0tCgojU0JBVENIIC1KIG1lcmdlX2tpbmdkb21zCiNTQkFUQ0ggLS10aW1lPTE6MDA6MDAKI1NCQVRDSCAtLW50YXNrcz0xCiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS9tZXJnZWQgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtbyBsb2dzLzFfbWVyZ2Vfa2luZ2RvbXNfJWoub3V0CiNTQkFUQ0ggLUEgc3RyYXVzcwoKZGF0ZTtob3N0bmFtZTtwd2QKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMKIyBUaGlzIHNjcmlwdCB3aWxsIG1lcmdlIHRoZSBJVFMgYW5kIDE2UyB0YWJsZSBhbmQgdGF4b25vbXkgYXJ0aWZhY3RzIAojIAojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KY3AgLi4vSVRTL2ZlYXR1cmVzL3RhYmxlLnF6YSB0YWJsZV9JVFMucXphCmNwIC4uL0lUUy9mZWF0dXJlcy90YXhvbm9teS5xemEgdGF4b25vbXlfSVRTLnF6YQpjcCAuLi9JVFMvZmVhdHVyZXMvcmVwLXNlcXMucXphIHJlcHNlcXNfSVRTLnF6YQpjcCAuLi8xNlMvZmVhdHVyZXMvdGFibGUucXphIHRhYmxlXzE2Uy5xemEKY3AgLi4vMTZTL2ZlYXR1cmVzL3RheG9ub215LnF6YSB0YXhvbm9teV8xNlMucXphCmNwIC4uLzE2Uy9mZWF0dXJlcy9yZXAtc2Vxcy5xemEgcmVwc2Vxc18xNlMucXphCgpxaWltZSBmZWF0dXJlLXRhYmxlIG1lcmdlIFwKICAtLWktdGFibGVzIHRhYmxlXzE2Uy5xemEgXAogIC0taS10YWJsZXMgdGFibGVfSVRTLnF6YSBcCiAgLS1wLW92ZXJsYXAtbWV0aG9kIGVycm9yX29uX292ZXJsYXBwaW5nX2ZlYXR1cmUgXAogIC0tby1tZXJnZWQtdGFibGUgdGFibGUucXphCgpxaWltZSBmZWF0dXJlLXRhYmxlIG1lcmdlLXRheGEgXAogIC0taS1kYXRhIHRheG9ub215XzE2Uy5xemEgXAogIC0taS1kYXRhIHRheG9ub215X0lUUy5xemEgXAogIC0tby1tZXJnZWQtZGF0YSB0YXhvbm9teS5xemEKCnFpaW1lIGZlYXR1cmUtdGFibGUgbWVyZ2Utc2VxcyBcCiAtLWktZGF0YSByZXBzZXFzXzE2Uy5xemEgXAogLS1pLWRhdGEgcmVwc2Vxc19JVFMucXphIFwKIC0tby1tZXJnZWQtZGF0YSByZXAtc2Vxcy5xemEKCnFpaW1lIGZlYXR1cmUtdGFibGUgc3VtbWFyaXplIFwKIC0taS10YWJsZSB0YWJsZS5xemEgXAogLS1vLXZpc3VhbGl6YXRpb24gdGFibGUucXp2IFwKIC0tbS1zYW1wbGUtbWV0YWRhdGEtZmlsZSAuLi9ibGFibGEgICAgIAkJICAgICAgICAgICNJTlNFUlQgUEFUSCBUTyBWQUxJREFURUQgTUFQUElORyBGSUxFCgpxaWltZSB0b29scyBleHBvcnQgXAogIC0taW5wdXQtcGF0aCB0YXhvbm9teS5xemEgXAogIC0tb3V0cHV0LXBhdGggLgoKc2VkIC1pIHMvVGF4b24vdGF4b25vbXkvIHRheG9ub215LnRzdiB8IHNlZCAtaSBzL0ZlYXR1cmVcIElEL0ZlYXR1cmVJRC8gdGF4b25vbXkudHN2Cgptb2R1bGUgdW5sb2FkIHFpaW1lMgoKZGF0ZQoKYGBgCkV4aXQgdXNpbmcgYGN0cmwgKyBYYCBhbmQgc2F2ZSB3aXRoIGBZYC4gVGhlbiBkbwpgYGB7YmFzaCwgZXZhbD1GQUxTRX0Kc2JhdGNoIHNjcmlwdHMvb3B0X3RyYWluX3NrbGVhcm5fVU5JVEUuc2gKYGBgCgojIzJfdG9fYmlvbV9hbmRfYmV5b25kLnNoClRoaXMgc2NyaXB0IHdpbGwgbm93IGNvbnZlcnQgdGhlIHRhYmxlcyBpbnRvIFBoeWxvc2VxLXJlYWRhYmxlIGZpbGVzIGFuZCBwcm9kdWNlIGFsc28gbm9ybWFsaXplZCB0YWJsZXMgdXNpbmcgdGhlIERFU0VxMiBhbGdvcml0aG0gKGh0dHA6Ly9nZW5vbWViaW9sb2d5LmNvbS8yMDE0LzE1LzEyLzU1MCkuIEZvciB3aHkgdGhpcyBpcyBiZXR0ZXIgdGhhbiByYXJlZmFjdGlvbiwgcGxlYXNlIHJlZmVyIHRvIHRoZSBXYXN0ZSBub3QsIHdhbnQgbm90IHBhcGVyIChodHRwczovL2pvdXJuYWxzLnBsb3Mub3JnL3Bsb3Njb21wYmlvbC9hcnRpY2xlP2lkPTEwLjEzNzEvam91cm5hbC5wY2JpLjEwMDM1MzEpCgpXYXRjaCBvdXQ6IGluIG9yZGVyIHRvIG9idGFpbiBjb3JyZWN0IGZpbHRlcmluZyAKYGBge2Jhc2gsIGV2YWw9RkFMU0V9Cm5hbm8gc2NyaXB0cy8yX3RvX2Jpb21fYW5kX2JleW9uZC5zaApgYGAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLS1tZW09MjBnCiNTQkFUQ0ggLS10aW1lPTg6MDA6MDAKI1NCQVRDSCAtTiAxCiNTQkFUQ0ggLUogcTJfdG9fYmlvbQojU0JBVENIIC1vIGxvZ3MvMl9xMl90b19iaW9tXyVqLm91dAojU0JBVENIIC1EIC91ZnJjL3N0cmF1c3MveW91cl9hY2NvdW50L3lvdXJfd29ya2luZ19kaXJlY3RvcnkvbWVyZ2VkICAjUEFUSCBPRiBZT1VSIFdPUktJTkcgRk9MREVSCiNTQkFUQ0ggLUEgc3RyYXVzcwoKZGF0ZTtob3N0bmFtZTtwd2QKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIwojIEZpbHRlcnMgbG93IGZyZXF1ZW5jeSBmZWF0dXJlcywgYW5kIHVud2FudGVkIHRheGEsIGV4cG9ydHMgdG8gQmlvbSBKU09OIGFuZAojIG5vcm1hbGl6ZXMgdGFibGVzIHVzaW5nIENTUyBhbmQgREVTZXEyIGFsZ29yaXRobXMKIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Mb2FkIE1vZHVsZXMtLS0tLS0tLS0tLS0tLS0tLS0tLQptb2R1bGUgbG9hZCBxaWltZTIKCiMgLS0tLS0tLS0tLS0tLS0tLUhvdXNla2VlcGluZy0tLS0tLS0tLS0tLS0tLS0tLS0tCnJtIC1yIGJpb20KbWtkaXIgZmVhdHVyZXMKbXYgICoucXphIGZlYXR1cmVzLwptdiB0YXhvbm9teS50c3YgZmVhdHVyZXMvdGF4b25vbXkudHN2CmNkIGZlYXR1cmVzCgojIC0tLS0tLS0tLS0tLS0tLS0tLUNvbW1hbmRzLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKcWlpbWUgdG9vbHMgZXhwb3J0IFwKICAtLWlucHV0LXBhdGggdGFibGUucXphIFwKICAtLW91dHB1dC1wYXRoIC4uL2Jpb20KCnFpaW1lIHRvb2xzIGV4cG9ydCBcCiAgLS1pbnB1dC1wYXRoIHRheG9ub215LnF6YSBcCiAgLS1vdXRwdXQtcGF0aCAuLi9iaW9tCgptb2R1bGUgdW5sb2FkIHFpaW1lMgptb2R1bGUgbG9hZCBxaWltZS8xLjkuMQoKY2QgLi4vYmlvbQoKYmlvbSBjb252ZXJ0IFwKICAtaSBmZWF0dXJlLXRhYmxlLmJpb20gXAogIC1vIGZlYXR1cmUtanNvbi5iaW9tIFwKICAtLXRhYmxlLXR5cGU9Ik9UVSB0YWJsZSIgXAogIC0tdG8tanNvbgoKc2VkIC1pIHMvVGF4b24vdGF4b25vbXkvIHRheG9ub215LnRzdiB8IHNlZCAtaSBzL0ZlYXR1cmVcIElEL0ZlYXR1cmVJRC8gdGF4b25vbXkudHN2CgpiaW9tIGFkZC1tZXRhZGF0YSBcCiAgLWkgZmVhdHVyZS1qc29uLmJpb20gXAogIC1vIGZlYXR1cmVfd190YXguYmlvbSBcCiAgLS1vYnNlcnZhdGlvbi1tZXRhZGF0YS1mcCB0YXhvbm9teS50c3YgXAogIC0tb2JzZXJ2YXRpb24taGVhZGVyIEZlYXR1cmVJRCx0YXhvbm9teSxDb25maWRlbmNlIFwKICAtLXNjLXNlcGFyYXRlZCB0YXhvbm9teSAtLWZsb2F0LWZpZWxkcyBDb25maWRlbmNlCgpmaWx0ZXJfc2FtcGxlc19mcm9tX290dV90YWJsZS5weSBcCiAgLWkgZmVhdHVyZV93X3RheC5iaW9tIFwKICAtbyBmaWx0ZXJlZC10YWJsZS5iaW9tIFwKICAtbiAxCgpmaWx0ZXJfdGF4YV9mcm9tX290dV90YWJsZS5weSBcCiAgLWkgZmlsdGVyZWQtdGFibGUuYmlvbSBcCiAgLW8gdGFibGVfd29fY2hsX21pdC5iaW9tIFwKICAtbiBEXzJfX0NobG9yb3BsYXN0LERfNF9fTWl0b2Nob25kcmlhCgpub3JtYWxpemVfdGFibGUucHkgXAogIC1pIHRhYmxlX3dvX2NobF9taXQuYmlvbSBcCiAgLWEgREVTZXEyIFwKICAtLURFU2VxX25lZ2F0aXZlc190b196ZXJvIFwKICAtbyBERVNlcTJfdGFibGUuYmlvbQoKYmlvbSBhZGQtbWV0YWRhdGEgXAogIC1pIERFU2VxMl90YWJsZS5iaW9tIFwKICAtbyBERVNlcTJfd190YXguYmlvbSBcCiAgLS1vYnNlcnZhdGlvbi1tZXRhZGF0YS1mcCB0YXhvbm9teS50c3YgXAogIC0tb2JzZXJ2YXRpb24taGVhZGVyIEZlYXR1cmVJRCx0YXhvbm9teSxDb25maWRlbmNlIFwKICAtLXNjLXNlcGFyYXRlZCB0YXhvbm9teSAtLWZsb2F0LWZpZWxkcyBDb25maWRlbmNlCgpub3JtYWxpemVfdGFibGUucHkgXAogIC1pIHRhYmxlX3dvX2NobF9taXQuYmlvbSBcCiAgLWEgQ1NTIFwKICAtbyBDU1NfdGFibGUuYmlvbQoKcm0gZmVhdHVyZS50c3YKcm0gZmVhdHVyZS1oZGY1LmJpb20KCmJpb20gY29udmVydCBcCiAtaSB0YWJsZV93b19jaGxfbWl0LmJpb20gXAogLW8gZmVhdHVyZS10YWJsZS50c3YgXAogLS10by10c3YgXAogLS10YWJsZS10eXBlICJPVFUgdGFibGUiCgpzZWQgLWkgcy8iI09UVSBJRCIvRmVhdHVyZUlELyBmZWF0dXJlLXRhYmxlLnRzdgpzZWQgLWkgJzFkJyBmZWF0dXJlLXRhYmxlLnRzdgoKbW9kdWxlIHVubG9hZCBxaWltZQptb2R1bGUgdW5sb2FkIHB5dGhvbgoKZGF0ZQpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8yX3RvX2Jpb21fYW5kX2JleW9uZC5zaApgYGAKCiMjM19idWlsZF90cmVlLnNoCkZpbmFsbHksICB0aGlzIHNjcmlwdCB3aWxsIHVzZSB0aGUgbWVyZ2VkIHNlcXVlbmNlcyB0byBidWlsZCBhIG5ldyB0cmVlLiBOb3RlIHRoYXQgYm90aCB0aGlzIGFuZCB0aGUgcHJldmlvdXMgc2NyaXB0cyBjYW4gYWxzbyBiZSBhcHBsaWVkIHRvIHRoZSBjb3JyZXNwb25kZW50IGZpbGUgaGF2aW5nIHRoZSBzYW1lIG5hbWVzIGluIHRoZSAxNlMgb3IgdGhlIElUUyBmb2xkZXIsIGJ5IGNoYW5naW5nIHRoZSB3b3JraW5nIGRpcmVjdG9yeQpgYGB7YmFzaCwgZXZhbD1GQUxTRX0KbmFubyBzY3JpcHRzLzNfYnVpbGRfdHJlZS5zaApgYGAKCmBgYHtiYXNoLCBldmFsPUZBTFNFfQojIS9iaW4vYmFzaAoKIyAtLS0tLS0tLS0tLS0tLS0tU0xVUk0gUGFyYW1ldGVycy0tLS0tLS0tLS0tLS0tLS0KCiNTQkFUQ0ggLUogYnVpbGRfdHJlZQojU0JBVENIIC0tbWVtPTIwZwojU0JBVENIIC0tdGltZT04OjAwOjAwCiNTQkFUQ0ggLS1udGFza3M9MQojU0JBVENIIC1uIDEyCiNTQkFUQ0ggLUQgL3VmcmMvc3RyYXVzcy95b3VyX2FjY291bnQveW91cl93b3JraW5nX2RpcmVjdG9yeS9tZXJnZWQgICNQQVRIIE9GIFlPVVIgV09SS0lORyBGT0xERVIKI1NCQVRDSCAtbyBsb2dzLzNfcTJfdHJlZV8lai5vdXQKI1NCQVRDSCAtQSBzdHJhdXNzCgpkYXRlO2hvc3RuYW1lO3B3ZAoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIwojIEJ1aWxkcyB0cmVlIGZvciBmdXJ0aGVyIGFuYWx5c2lzIGFuZCBleHBvcnRzIGluIC50cmUgZm9ybWF0CiMgCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIC0tLS0tLS0tLS0tLS0tLS1Ib3VzZWtlZXBpbmctLS0tLS0tLS0tLS0tLS0tLS0tLQpjZCBiaW9tCnJtIGFsaWduZWQtcmVwLXNlcXMtZmlsdGVyZWQucXphCnJtIG1hc2tlZC1hbGlnbmVkLXJlcC1zZXFzLWZpbHRlcmVkLnF6YQpybSB1bnJvb3RlZC10cmVlLWZpbHRlcmVkLnF6YQpybSByb290ZWQtdHJlZS1maWx0ZXJlZC5xemEKcm0gLXIgKi5ud2sKCiMgLS0tLS0tLS0tLS0tLS0tLUxvYWQgTW9kdWxlcy0tLS0tLS0tLS0tLS0tLS0tLS0tCm1vZHVsZSBsb2FkIHFpaW1lMgoKIyAtLS0tLS0tLS0tLS0tLS0tLS1Db21tYW5kcy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCnFpaW1lIGZlYXR1cmUtdGFibGUgZmlsdGVyLXNlcXMgXAogLS1pLWRhdGEgLi4vZmVhdHVyZXMvcmVwLXNlcXMucXphIFwKIC0tbS1tZXRhZGF0YS1maWxlIGZlYXR1cmUtdGFibGUudHN2IFwKIC0tcC1uby1leGNsdWRlLWlkcyBcCiAtLW8tZmlsdGVyZWQtZGF0YSByZXAtc2Vxcy1maWx0ZXJlZC5xemEKCnFpaW1lIGFsaWdubWVudCBtYWZmdCBcCiAgLS1pLXNlcXVlbmNlcyByZXAtc2Vxcy1maWx0ZXJlZC5xemEgXAogIC0tcC1uLXRocmVhZHMgMTIgXAogIC0tby1hbGlnbm1lbnQgYWxpZ25lZC1yZXAtc2Vxcy1maWx0ZXJlZC5xemEKCnFpaW1lIGFsaWdubWVudCBtYXNrIFwKICAtLWktYWxpZ25tZW50IGFsaWduZWQtcmVwLXNlcXMtZmlsdGVyZWQucXphIFwKICAtLW8tbWFza2VkLWFsaWdubWVudCBtYXNrZWQtYWxpZ25lZC1yZXAtc2Vxcy1maWx0ZXJlZC5xemEKCnFpaW1lIHBoeWxvZ2VueSBmYXN0dHJlZSBcCiAgLS1pLWFsaWdubWVudCBtYXNrZWQtYWxpZ25lZC1yZXAtc2Vxcy1maWx0ZXJlZC5xemEgXAogIC0tby10cmVlIHVucm9vdGVkLXRyZWUtZmlsdGVyZWQucXphCgpxaWltZSBwaHlsb2dlbnkgbWlkcG9pbnQtcm9vdCBcCiAgLS1pLXRyZWUgdW5yb290ZWQtdHJlZS1maWx0ZXJlZC5xemEgXAogIC0tby1yb290ZWQtdHJlZSByb290ZWQtdHJlZS1maWx0ZXJlZC5xemEKCnFpaW1lIHRvb2xzIGV4cG9ydCBcCiAgLS1pbnB1dC1wYXRoIHJvb3RlZC10cmVlLWZpbHRlcmVkLnF6YSBcCiAgLS1vdXRwdXQtcGF0aCAuCgptb2R1bGUgdW5sb2FkIHFpaW1lMgoKZGF0ZQpgYGAKRXhpdCB1c2luZyBgY3RybCArIFhgIGFuZCBzYXZlIHdpdGggYFlgLiBUaGVuIGRvCmBgYHtiYXNoLCBldmFsPUZBTFNFfQpzYmF0Y2ggc2NyaXB0cy8zX2J1aWxkX3RyZWUuc2gKYGBgCgoK